# Rolling three dice and show the probabilities

Roll 3 dice, count the two highest two values and add them to the result. Every 1 must be rolled once again.

Now show the average throw after 1000000 tries and the probabilities for each result occurring:

# Desired Result:

avg(9.095855)
2: 0.0023
3: 0.0448
4: 1.1075
5: 2.8983
6: 6.116
7: 10.1234
8: 15.4687
9: 18.9496
10: 19.3575
11: 16.0886
12: 9.8433

-
Are we required to throw random dice, or may we calculate the probabilities directly? – primo Dec 15 '12 at 6:22
In the second sentence, do you mean "Every 1 must be rolled once again"? Yeah, I mean, I know you do, but it can be read literally as "or you can leave it if you can't be bothered" and that would result in a shorter algorithm! – Mr Lister Dec 15 '12 at 17:09
Random of course, and you're right, must is more fun ;) – Sven Dec 15 '12 at 18:25
So, that is roll 3 dice, re-roll the 1s, take away to lowest die, sum the two, and repeat 1mil times? – TwiNight Jan 3 '13 at 5:34
Still unclear to me: what if I get a 1 and reroll it once again and get a 1 again? – edc65 Jul 5 '15 at 9:40

# Mathematica 150 146 94 115 108

Edit: This version is a suggestion from @belisarius. Much shorter and faster than my own code (found in the earlier versions).

``````r=RandomInteger;t=Tr/@Rest/@Sort/@(5~r~{10^6,3}/. 0:>r[5]);
{Mean@t+2,{#[[1]]+2,#[[2]]/10^4}&/@Sort@Tally@t}//N
``````

{9.09684, {{2., 0.0028}, {3., 0.0456}, {4., 1.1097}, {5., 2.8752}, {6., 6.1246}, {7., 10.122},
{8., 15.513}, {9., 18.8956}, {10., 19.3514}, {11., 16.074}, {12., 9.8861}}}

-
In 96: `r=RandomInteger;{#[[1]]+2,#[[2]]/10^4}&/@Sort@Tally[Tr/@Rest/@Sort/@(5~r~{10^6,‌​3}/. 0:>r[5])]//N` – Dr. belisarius Dec 16 '12 at 16:57
I get the following message with your code: RandomInteger::array: "The array dimensions {1000000,3\ ‌} given in position 2 of RandomInteger[5,{1000000,3\ ‌}] should be a list of non-negative machine-sized integers giving the dimensions for the result. " – DavidC Dec 16 '12 at 17:01
`r = RandomInteger; {#[[1]] + 2, #[[2]]/10^4} & /@ Sort@Tally[Tr /@ Rest /@ Sort /@ (5~r~{10^6, 3} /. 0 :> r[5])] // N` – Dr. belisarius Dec 16 '12 at 17:03
Works. And about 10000 x faster than mine. Why don't you submit it as your own? – DavidC Dec 16 '12 at 17:08
Feel free to include it as an upgrade to your answer. I usually don't like answering in this site because the input/output is often required in a way more fitted to other languages. – Dr. belisarius Dec 16 '12 at 17:23

## APL 110 103

``````r←11⍴0
i←1
l:r←r+(j←1+⍳11)=+/2↑n[⍒n←3↑((3↑x)~1),3↓x←?6⍴6]
i←i+1
→(i≤k←10*6)/l
((+/r×j)÷k)
j,[1.1]r÷10*4
``````

I have included the results of three runs to demonstrate the degree of repeatability over 1000000 iterations.

``````9.092186    9.093053    9.093897
2  0.0022   2  0.0019   2  0.0023
3  0.0442   3  0.0477   3  0.0452
4  1.1064   4  1.0755   4  1.0866
5  2.8808   5  2.887    5  2.8771
6  6.1472   6  6.1864   6  6.1485
7 10.1532   7 10.1163   7 10.1575
8 15.6376   8 15.5511   8 15.5834
9 18.8736   9 18.918    9 18.873
10 19.2771  10 19.3763  10 19.3315
11 15.9702  11 16.0225  11 16.0529
12  9.9075  12  9.8173  12  9.8419
``````
-
Very golfable. `r←r+`==`r+←`, `((3↑x)~1)`==`(1~⍨3↑x)`, `10*6`==`1e6`, `,[1.1]`==`,[⍟3]` – TwiNight Jan 3 '13 at 17:29
@TwiNight I am afraid all bar 1e6 will not work in an early version of APL+Win. I do not have the luxury of dynamic function either. Thanks all the same. – Graham Jan 3 '13 at 22:01

## Python (207 194 189)

``````from random import*
a=lambda:randint(13,48)/7
r=range
x=[0]*13
s=0
for i in r(10**6):b=sum(sorted([a(),a(),a()])[1:]);x[b]+=1e-4;s+=b/1e6
print'avg(%f)'%s
for i in r(2,13):print`i`+':',x[i]
``````

Algorithm:

``````a is the RNG, x is the list which contains the results, s is the sum. r is for code-golfing purposes.
1. Iterate through steps 2-6 1,000,000 times:
2. Get three random numbers from `a` and put them in a list.
3. Sort the list. (list is now in ascending order)
4. Take the sum of every item but the first item in the list. Call this number b.
5. Increment the (b)th index of x by 1e-4 (1/10000).
6. Increment s by b * 1e-6 (1/1000000).
7. Print out s.
8. For each item in x (excluding the first two), output the item.
``````
-

# APL, 67

``````÷1e2÷+/×/x←⍉↑n,1e4÷⍨+/(n←⊂⍳12)∘.={+/2↑x[⍒x←{⍵=1:?6⋄⍵}¨?3⍴6]}¨⍳1e6⋄x
``````

### Explanation

• `⍳1e6` Create array from 1 to milliion,
• `¨` and for each of those
• `{+/2↑x[⍒x←{⍵=1:?6⋄⍵}¨?3⍴6]}` do a roll, re-roll 1s, and sum the high dices:

`?3⍴6` roll 3 dice,
`¨` and for each die
`{⍵=1:?6⋄⍵}` if it is a 1, replace it by a re-roll result, else don't change it.
`x←` Save the result in (local) variable `x`,
`x[⍒x`...`]` sort it in descending order,
`+/2↑` take the first 2 items (high dices) and return the sum.

• `+/(n←⊂⍳12)∘.=` Create array of the no. of times each sum appears,
• `1e4÷⍨` divide by 10000,
• `⍉↑n,` insert a row to the top with numbers 1 to 12, and matrix transpose it. The result would be something like the table in the question.
• `x←` Save that in (global) variable `x`.
• `+/×/` Calculate the average of the million rolls by multiplying the columns, summing those...
• `÷1e2÷` and divide by 100.

The result is displayed (by default)

• `⋄x` Finally, output `x`

### Example output

```9.097008
1  0
2  0.0028
3  0.0466
4  1.0914
5  2.8873
6  6.0957
7 10.1242
8 15.6108
9 18.8688
10 19.2834
11 16.0979
12  9.8911```

### Notes

-5 chars if allowed to represent 10% by 0.1 instead of 10
-3 chars if allowed to use probabilistic approach (like o_o's) instead of explicit re-roll
+12 chars if the "avg()" is required
+2 chars if the "1" row needs to be removed
+8 chars if the colon is required in output

-

## Python, 262

``````import random
r=random.randint
def f():n=r(1,6);return n if n>1 else r(1,6)
l=[0.0]*13
for i in range(10**6):l[sum(sorted([f(),f(),f()])[1:])]+=1
m=zip(*[range(2,13),l[2:]])
print'avg('+`sum([a*b for a,b in m])/10**6`+')'
for e in m:print`e[0]`+': '+`e[1]/10**4`
``````

results:

``````avg(9.098773)
2: 0.0021
3: 0.044
4: 1.0872
5: 2.89
6: 6.0982
7: 10.133
8: 15.5
9: 18.949
10: 19.2908
11: 16.0953
12: 9.9104
``````
-
Please show your results. I'm curious. – DavidC Dec 15 '12 at 13:57

# C# (599)

``````using System;using System.Collections.Generic;using System.Linq;namespace P{public class D{Random r=new Random(System.DateTime.Now.Millisecond);public static void Main(){var d=new D();d.G();}public int R(){return r.Next(1,7);}public int RD(){var e=new List<int>();for(var i=0;i<=2;i++){var v = R();e.Add(v != 1 ? v : R());}return e.OrderByDescending(d=>d).Take(2).Sum();}public void G(){const double l = 1000000;var t = new Dictionary<int,double>();for(var i=2;i<=12;i++)t.Add(i,0);for(var i=0;i<l;i++){var s=RD();t[s]=t[s]+1;}foreach(var a in t){Console.WriteLine(a.Key+": "+(a.Value)/10000.0);}}}}
``````
-
please read codegolf.stackexchange.com/faq and provide a golfed version of your answer (the least you can do is have one letter variables, inline methods where possible and avoid unnecessary whitespace). Also, provide a character count in the post title. – w0lf Dec 15 '12 at 9:23

## Perl (177169 168)

``````sub r{1+int rand 6}
for(1..1e6){@l=sort map{(\$q=r)>1?\$q:r}(1..3);++\$s{\$y=\$l[1]+\$l[2]};\$t+=\$y}
print"avg(".\$t/1e6.")\n";print"\$_: ".\$s{\$_}/1e4."\n"for sort{\$a<=>\$b}keys%s
``````

(NOTE: one-liner wrapped for clarity)

stacked output of three consecutive runs:

``````avg(9.09432)  avg(9.094793)  avg(9.092179)
2: 0.002      2: 0.0026      2: 0.0023
3: 0.0448     3: 0.0454      3: 0.0436
4: 1.0872     4: 1.0904      4: 1.0944
5: 2.8834     5: 2.8933      5: 2.8842
6: 6.1387     6: 6.127       6: 6.1854
7: 10.1648    7: 10.177      7: 10.1669
8: 15.498     8: 15.5758     8: 15.508
9: 18.9483    9: 18.8391     9: 18.9236
10: 19.3557   10: 19.278     10: 19.3234
11: 16.0589   11: 16.0863    11: 16.0256
12: 9.8182    12: 9.8851     12: 9.8426
``````

• shortening 1: eliminate `\$n=1e6` (insp. by Joe)
• shortening 2: del space in `keys %s`
-

## R - 98

``````S=sample
D=matrix(S(6,3e6,T),3)
D[D<2]=S(6,3e6,T)
A=colSums(D)-apply(D,2,min)
mean(A)
table(A)/1e4
``````

Like some other answers, my output is not in the same format as the OP; I was not sure if it was a strict requirement or not:

``````[1] 9.095695

A
2       3       4       5       6       7       8       9      10      11      12
0.0018  0.0426  1.1008  2.8748  6.1438 10.1147 15.5406 18.9276 19.3525 16.0126  9.8882
``````
-

# TI-BASIC, not an entry

This does not meet the spec, because it doesn't show the result distribution or directly roll integers between 1 and 6, but I found a slightly clever algorithm for computing the average in one line. To get the largest two dice rolls, we pad a number larger than any of the dice rolls onto the list of three rolls, and take the median, which will be the average of the middle two numbers (two highest dice rolls). Then we just multiply by 2 to get the sum.

``````2ᴇ~6Σ(median(int(augment(15+36rand(3),{99})/7)),X,1,ᴇ6
``````

Based on the speed of SuperJedi224's answer to "Death by Shock Probe", it will take over 12 hours to finish running.

-

# LUA (307)

``````function r()
m=math.random(1,6)
if(m==1)then return math.random(1,6)end
return m
end
e={}
s=0
o=1000000
for i=2,12 do e[i]=0 end
for t=1,o do
d={}
for i=1,3 do d[i]=r() end
table.sort(d)
x=d[2]+d[3]
e[x]=e[x]+1
s=s+x
end
print("avg("..s/o..")")
for i=2,12 do print(i..": "..e[i]/o*100) end
``````

My first one ;)

-
You may be able to shave off some bytes by using 10^6 and by assigning random(1,6) to a function with a shorter name, such as `f`. – DavidC Dec 15 '12 at 14:02

Seems to be a basic problem with the calculation and results I am seeing here.

If you must reroll the dice (all 3 or just one) when you get a 1 showing up, then the lowest possible sum of die faces you could ever have would be 4. That is, any face that shows a 1 will be rerolled. Which specifically requires that the lowest possible face is a 2. You could avoid the rerolling by generating random values from 2 .. 6, but that might be missing the point.

What this means: If you are reporting values for 2 or 3 as the sum of the faces, these are 1+1 and 2+1 respectively, the specification excludes this possibility.

That is, unless the "you must reroll the dice" only applies to the first instance of a 1. In which case, you may have a 1+1, and 2+1 case (so you'd get sums of 2 and 3 as possible answers).

-
Do you have code which implements this algorithm? CG&PP is less about explaining the algorithm, and more about implementing it (in the least amount of chars possible.) – beary605 Dec 16 '12 at 23:06
I understand this ... but the issue is that the results posted don't seem to match the specs. If you are reporting values for sum of faces = 1, 2, or 3 in your probability calcs, you have an implementation issue that needs to be resolved. That is, the algorithm as specified would never have a sum of faces less than 4. – Joe Dec 16 '12 at 23:40
You only reroll once. Basically, you have a 1/36 chance of rolling a 1, and a 7/36 chance of rolling anything else. I hope that makes it a little clearer :) – beary605 Dec 17 '12 at 2:25
``````map{@f=(sort((&r,&r,&r)[1,2]));\$d[\$f[0]+\$f[1]]++}(1..1E6);
map{\$s+=\$d[\$_]*\$_}(0..\$#d);print"avg(".\$s/1E6.")\n";map{print"\$_:
".\$d[\$_]/1E4."\n"}(0..\$#d);
sub r{\$x=1+int(rand 6);\$x>1?\$x:&r}

~/play/golf/dice\$ perl dice.pl
avg(8.000533)
0: 0
1: 0
2: 0
3: 0
4: 3.9796
5: 8.0376
6: 11.9607
7: 16.0064
8: 20.0094
9: 15.9636
10: 12.0582
11: 8.0057
12: 3.9788
``````
-

Now a more optimized version, with a shifted RNG (no reroll), and shortened statistics calcs, also exploiting the ordering due to the ascii nature of single integers.

``````map{@f=(sort((&r,&r,&r)[1,2]));\$i=\$f[0]+\$f[1];\$d[\$i]++;\$s+=\$i}(1..1E6);
print"avg(".\$s/1E6.")\n";map{print"\$_: ".\$d[\$_]/1E4."\n"}(0..\$#d);
sub r{2+int(rand 5)}
``````

As you can see, printing uses almost as much space as computing here. If you'd like a simpler output, this would save characters.

``````avg(8.000901)
0: 0
1: 0
2: 0
3: 0
4: 4.0007
5: 7.9769
6: 11.9652
7: 16.0226
8: 20.0156
9: 16.0389
10: 11.9983
11: 7.9861
12: 3.9957
``````
-
hey, i'll take some inspiration from you and reshuffle some code in my solution, but i'll still use a hash for statistics (whose keys i however unfortunately have to sort with explicit comparison finally), i wonder can get it shorter.. (i count one-liner size, before wrapping).. btw, you can omit `&` in `&r`, can't? and i think you should follow the requirements exactly (rerolling 1's one), to get the statistics right. – mykhal Dec 17 '12 at 1:39
Yes, this answer doesn't seem to fit the requirements of the question. Also, you can just edit your previous answer in-place instead of posting a completely new one. People can just click a link if they want to see what changed between edits. – JoeFish Dec 18 '12 at 21:31
Your language? your byte count? As is, this is worth a downvote – edc65 Jul 5 '15 at 10:05

## C 222 204 203

204: Updates from ugoren's comment, recycled more global vars, changed `D()` into a macro to save a `return` and three pairs of `()`.

203: Moved the first `printf` into the `for` to save a semicolon.

``````#define D (t=rand()%6)?t:rand()%6
j,i,f[11],s,t;M(a,b,c){t=a<b?a:b;t=c<t?c:t;t=a+b+c-t;}main(){for(;j++<1e6;M(D,D,D),s+=t+2)++f[t];for(printf("avg(%f)\n",s/1e6);i<11;++i)printf("%d: %f\n",i+2,f[i]/1e4);}
``````

``````#define D (t=rand()%6)?t:rand()%6
j,i,f[11],s,t;
M(a,b,c)
{
t=a<b?a:b;
t=c<t?c:t;
t=a+b+c-t;
}
main()
{
for(;j++<1e6;M(D,D,D),s+=t+2)
++f[t];
for(printf("avg(%f)\n",s/1e6);i<11;++i)
printf("%d: %f\n",i+2,f[i]/1e4);
}
``````
```avg(9.095219)
2: 0.001600
3: 0.045200
4: 1.100000
5: 2.903400
6: 6.124600
7: 10.112100
8: 15.556000
9: 18.876400
10: 19.358200
11: 16.053800
12: 9.868700
Press any key to continue . . .```
-
Some tips: `M` can set `t` directly. Saves `return`. `D` can return `(m=rand()%6)?m:rand()%6` (or with `gcc` - `rand()%6?:rand()%6`. In the first `for`, move something from the increment to the loop body (saves a comma). Give `main` a parameter (saves a comma). – ugoren Dec 18 '12 at 14:56
Ah thanks! I was looking for ways to use a global in `M()` but couldn't get my head aroudn it. – JoeFish Dec 18 '12 at 14:57
Some more: In `M`, merge the 2nd and 3rd lines to save an assignment. In the `printf`, use `j` as `1e6`. You can define `main(i)` and loop with `++i<13`, then `i` runs from 2 to 12. – ugoren Dec 19 '12 at 9:00

## C - 200

I didn't bother to re-roll on 1, instead I used the probability distribution (1/36 chance of rolling 1, 7/36 chance of rolling anything else). Hopefully this is acceptable. Newline has been inserted for clarity.

``````#define D 6-rand()%36/7
a,b,c,t,u,w,y[13];
main(v,q){srand(q);for(;v++<=1e6;u=(a=D)<(b=D)?a:b,w+=t=a+b+(c=D)-(u<c?u:c))y[t]++;
printf("avg(%f)\n",w/1e6);for(v=1;++v<13;)printf("%d: %f\n",v,y[v]/1e4);}
``````

After compilation (gcc -O3) - 1 run

``````avg(9.096896)
2: 0.002200
3: 0.043100
4: 1.093900
5: 2.891000
6: 6.110100
7: 10.091400
8: 15.605000
9: 18.936500
10: 19.258800
11: 16.047100
12: 9.920800
``````
-

## CoffeeScript, 146

``````r=()->~~(6*Math.random())
t=i=0;s=[];(a=[r()||r(),r()||r(),r()||r()].sort();t+=b=2+a[1]+a[2];s[b]=1e2/z+(s[b]||0))while++i<z=1e6;console.log t/z,s
``````

Outputs the average and an object:

``````9.09456
[2: 0.0022, 3: 0.043400000000000216, 4: 1.103199999999895, 5: 2.9063000000017087, 6: 6.142699999999023, 7: 10.075099999989858, 8: 15.533299999977137, 9: 18.94439999996919, 10: 19.328099999968295, 11: 16.106199999975804, 12: 9.814999999990464]
``````
-

## JavaScript (ES6), 149

Algorithm is similar to my CoffeeScript answer; different syntax and semantics. I tried inlining the `q` function here which made no difference.

``````for(r=()=>~~(6*Math.random()),q=()=>r()||r(),t=i=0,s={};++i<(z=1e6);){a=[q(),q(),q()].sort();t+=b=2+a[1]+a[2];s[b]=1e2/z+(s[b]||0)}console.log(t/z,s)
``````

### Unminified

``````for (
r = () => ~~ (6 * Math.random()), // function to generate random number between 0 - 5
q = () => r() || r(),           // function to roll dice and if 0, re-roll once
t = i = 0,                      // initialize counter and sum
s = {};                         // initialize probability object
++i < (z = 1e5);                  // increment
) {
a = [q(), q(), q()].sort();       // roll three dice and perform lexicographical sort
t += b = 2 + a[1] + a[2];         // take two highest and add 2 since numbers are 0 - 5
s[b] = 1e2 / z + (s[b] || 0)      // put into probability object as a percent
}
console.log(t / z, s)                 // STDOUT
``````
-