Hello friendly Julia community,
Suppose I have an integer. How do I convert this to an array?
Specifically, I have a counter inside a local namespace of a function, call it,
counts, and when I println it, I get:
What I am interested is only the last value: here, 4.
I cannot use the [array][end] on it because
counts is not an array yet. I tried the manual and online suggestions but no cigar.
Any suggestion will be highly appreciated.
I am not sure that you need an array to get the last value of a counter, just return counter after the last iteration.
Converting an int to an array
julia> a = 4
julia> b = 
julia> b = [a]
I do not quite understand your question either.
Below is a solution, although there are probably more elegant approaches
Of course, if you do not need the array, you should comment that code.
counter = i^2 + counter
Thank you Fred! this is what I needed as well. It is good to see that Julia type-conversion is hassle-free.
Good day! As a thank you, I suggest this excellent book for you! (Body by Science, By Little).
Exactly what I needed. While you were writing the answer, I tinkered as well and came up with this:
p1, p2 = 0, 0
counts = 
for i in 1:n
p1, p2 = rand(1:6, 6), rand(1:4, 9)
if sum(p1) == sum(p2)
counts = push!(counts, 0)
elseif sum(p1)> sum(p2)
counts = push!(counts, 1)
Although not as Julian as yours, I think I obviated the type conversion by initializing an empty array for
counts, instead of simply
This code is for https://projecteuler.net/problem=205 so I guess I still need to modify it since it does not look right.
Here is a more-Julian way to do this efficiently:
count = 0
trials = 0
x = rand(1:4, 9)
y = rand(1:6, 6)
while trials < n
p1 = sum( rand!(x, 1:4) )
p2 = sum( rand!(y, 1:6) )
p1 == p2 && continue # A draw
p1 > p2 && (count += 1)
trials += 1
return count / n # the Probability of p1 > p2
1.301851 seconds (8 allocations: 480 bytes)
Thank you Seif_Shebl!
Your code is fast.
OTOH, the answer it produces is not close to the correct one. The correct answer that unlocked the Project Euler quiz 205 is:
My code gave:
Which is correct to three decimal places…good enough for me, since the code itself is extremely readable and easy to write, although I must say, slower than yours. Your code gives:
Here is the answer and time for my code:
2.434311 seconds (21.62 M allocations: 2.710 GiB, 6.77% gc time)
So while it gives a correct answer to 3 decimal places (each time a slightly different answer), the speed and memory alloc could be improved… which I am going to borrow from your code. Thanks!
@Seif_Shebl’s code does not count the draws, that’s why the answer comes out wrong. The phrasing of the problem itself on the Project Euler page was a bit unclear.
Here’s a version that gives you the right answer, and is ~2x as fast as @Seif_Shebl’s one. It avoids creating any arrays at all:
count = 0
for trials in 1:n
p1 = sum(rand(1:4) for _ in 1:9)
p2 = sum(rand(1:6) for _ in 1:6)
count += (p1 > p2)
return count / n
It uses a generator for creating the sums, so zero allocations. Also, you can avoid branches (
&&) by realizing that you can do
count += (p1 > p2). This works because
n + false == n+0 while
n + true = n+1.
In order to get the correct number of significant digits, you should probably have some convergence criterion, so that you can tell when to stop iterating. Have you given any thought to that?
If you want an accurate answer, then you have to loop over all possibilities of outcomes for Peter’s rolls and compare each one with all the possibilities of outcomes for Colin’s rolls. This way, you will get the exact required probability. The algorithm of using random numbers converges very slowly, that is why you don’t get a correct answer in a reasonable time.
This can be done as follows (you can shrink all loops into just one using
Iterator but I’ll keep it simple and verbose here):
count = 0
total = 0
for p1 = 1:4, p2 = 1:4, p3 = 1:4, p4 = 1:4, p5 = 1:4, p6 = 1:4, p7 = 1:4, p8 = 1:4, p9 = 1:4
for c1 = 1:6, c2 = 1:6, c3 = 1:6, c4 = 1:6, c5 = 1:6, c6 = 1:6
count += p1+p2+p3+p4+p5+p6+p7+p8+p9 > c1+c2+c3+c4+c5+c6
total += 1
@printf("%.7f\n", count/total) # 0.5731441
Thank you for the neat code! Yup I think the value slightly changes because of the very good random-number generator in Julia.
But to get the ‘classical’ probability value I think a slightly longer code, like counting all the proportions would always give the same value…but I think it does not justify writing triple the amount of code just to get the same value each time.
Even Project Euler got it wrong in that true probabilistic outcomes solved by programming languages are always empirical and subject to some variation in the decimals.
I ran your code on 1 billion iterations for a time of 105 seconds–not bad–but the value is still:
Still, it makes for an interesting exercise. I spent a better part of the day trying to see if I could use binomial expansion to count all the proportions, but I am newbie to both probability and Julia, so still investigating…(it is surprising how poorly-written most probability texts are).
The solutions posted by all other people on Project Euler–frankly–were not impressive. The code is not readable, and most of the solutions at least double and in most cases triple the amount of code I have. They also use C++/Java which I really dislike, and the Python ones were also quite a mess. (no wonder I am here on Julia discourse).
Much impressed with this. I was looking for something like this the whole day yesterday.
Thank you very much! As a little gift, I recommend this excellent FREE book: “The Anatomy of Melancholy” by that great thinker, Robert Burton.
Is it a restriction that you have to use nested loops? It is not apparent to me from the description of 205. In any case, I would just do
die_distribution(sides) = [i => 1//sides for i in 1:sides]
combine(f, A, B) = [f(a, b) => p * q for (a, p) in A for (b, q) in B]
[first(first(g)) => sum(last, g)
for g in groupby(first, sort(A, by = first))]
reduce((A, B) -> aggregate(combine(+, A, B)), As)
T4 = total_distribution(fill(die_distribution(4), 9)) # Pete
T6 = total_distribution(fill(die_distribution(6), 6)) # Colin
P_beats_C = sum(((a, p),) -> a * p, combine(>, T4, T6))
If you are not allowed to use libraries,
groupby is fairly easy to substitute. If you are not allowed to use rationals, then you can keep track of denominators using integers, I was just lazy.
Project Euler doesn’t generally impose restrictions, rather the problem itself imposes enough restrictions most of the time, like really long runtimes with bad code or with a bad model of the problem.
Thanks. In that case, I think that simply using the convolutions (like I did) is by far the fastest and most accurate.
I was just surprised that people used Monte Carlo and nested loops and thought they were the result of a restriction.