Those of you who like Numberphile would be familiar with Dr. James Grime, who described a non-transitive dice game on his channel.
The game consists of three 6-faced dice:
- Die 1: 3,3,3,3,3,6
- Die 2: 2,2,2,5,5,5
- Die 3: 1,4,4,4,4,4
Two players each select a die to use. They roll them and the higher die wins, best-of-whatever.
Probabilistically, die 1 beats dies 2 with>50% chance. Similarly, die 2 beats die 3, and, interestingly, die 3 beats die 1.
Write a program taking 1, 2 or 3 as input. This indicates the die the user chooses. The program then choose the die that would beat the user and output the results of 21 rolls, and "Computer/User wins with x points"
Rules
- Code-golf, votes as tiebreaker
- You must use RNG (or the likes) to actually simulate the dice rolls.
- I am not too strict on output format. It's okay as long as you show the dices, somehow separate between the 21 rolls (in a way different from how you separate the dice in the same roll), and output that sentence above.
- Input can be stdin, command line argument, from screen, etc.
Example
Input
1
Output
4 3
4 3
4 3
4 3
4 3
4 3
4 3
4 3
4 3
4 6
1 3
4 3
4 3
1 3
4 3
1 3
4 3
4 3
4 3
4 3
4 6
Computer wins with 16 points
Here, the user chooses die 1 and his rolls are shown on the right column. The program chooses die 3 and beats him.
10 Answers 10
APL ((削除) 106 (削除ここまで) 114)
'Computer' 'User'[1+X],'wins with','points×ばつX←11>Z←+/>/⎕←⍉↑{⍵[{?6} ̈⍳21]} ̈(↓5 6⍴545170074510753⊤⍨18⍴7)[⎕+⍳2]
Explanation:
(↓5 6⍴545170074510753⊤⍨18⍴7)[⎕+⍳2]: The big number is a base-7 representation of the dice. We make a 6x5 matrix containing the values of the dice in the order: 2 3 1 2 3. Ask for user input and add this to the vector1 2, and select these lines from the matrix. Because the list of dice is shifted, the user now gets the one he selected (on the right) and the computer gets the stronger one.{⍵[{?6} ̈⍳21]} ̈: do 21 rolls for each of these two dice.⎕←⍉↑: put the rolls in matrix form and output them.Z←+/>/: get the score of the computer (amount of times the computer's value was higher than the user's)X←11>Z: setXto whether the user won (if 11 is higher than the computer's score).'Computer' 'User'[1+X].Xis whether the user won.'wins with','points×ばつX:Zis the computer's score, so if the computer won displayZ, otherwise display21-Z.
-
\$\begingroup\$ The score is not the difference of the totals (which is expected to be 0 for all pairs of dice), instead, the winner of each of the 21 rolls get 1 point. In the example, the user has 5 points (from winning 5 rolls: 4-6, 1-3, 1-3, 1-3, 4-6) and the computer get the 16 points rest. \$\endgroup\$TwiN– TwiN2013年01月10日 22:03:15 +00:00Commented Jan 10, 2013 at 22:03
-
\$\begingroup\$ @TwiNight: fixed it \$\endgroup\$marinus– marinus2013年01月11日 18:32:15 +00:00Commented Jan 11, 2013 at 18:32
-
\$\begingroup\$ Negative points when user wins. You can fix by
|Z-21×Xwhich doesn't change char count \$\endgroup\$TwiN– TwiN2013年01月11日 21:42:57 +00:00Commented Jan 11, 2013 at 21:42
R - 228
d=matrix(rep(c(rep(3,5),6,2,2,2,5,5,5,1,rep(4,5)),2),6)
x=scan()
r=expand.grid(Computer=d[,x+2],User=d[,x])[sample(36,21,T),]
print(r)
s=summary.factor(names(r)[max.col(r)])
cat(names(which.max(s)),"wins with",max(s),"points\n")
Example run:
> source('ntd.R')
1: 2
2:
Read 1 item
Computer User
28 3 5
31 3 5
36 6 5
18 6 2
11 3 2
31.1 3 5
14 3 2
8 3 2
9 3 2
17 3 2
2 3 2
29 3 5
3 3 2
16 3 2
4 3 2
21 3 5
14.1 3 2
23 3 5
16.1 3 2
17.1 3 2
19 3 5
Computer wins with 14 points
-
\$\begingroup\$ You can replace
summary.factorwithtable, saving 9 characters. \$\endgroup\$Brian Diggs– Brian Diggs2014年04月07日 17:28:24 +00:00Commented Apr 7, 2014 at 17:28
Mathematica (削除) 208 (削除ここまで) (削除) 172 (削除ここまで) (削除) 166 (削除ここまで) 159
Spaces added for clarity
b=Boole;{#, Row@{
If[# > 10, "Play", "Comput"], "er wins with ",
Max[#, 21 - #], " points"} &@ Total[b[#1 > #2] & @@@ #]} &@
Table[1 + i + 3 b[6 Random[] > 2 i + 1],{21}, {i, {#, Mod[# + 1, 3]}}] &
-
\$\begingroup\$ I think the output is supposed to list the values of each roll of the dice. \$\endgroup\$DavidC– DavidC2013年01月10日 01:45:51 +00:00Commented Jan 10, 2013 at 1:45
-
\$\begingroup\$ @dude yep, I lost it while testing. I made a quick fixup just to keep the ball running. I'll think later how to improve it. \$\endgroup\$Dr. belisarius– Dr. belisarius2013年01月10日 02:25:32 +00:00Commented Jan 10, 2013 at 2:25
-
\$\begingroup\$ It now seems to be working fine. \$\endgroup\$DavidC– DavidC2013年01月10日 03:28:24 +00:00Commented Jan 10, 2013 at 3:28
-
\$\begingroup\$ @dude Much better now \$\endgroup\$Dr. belisarius– Dr. belisarius2013年01月10日 20:16:05 +00:00Commented Jan 10, 2013 at 20:16
-
\$\begingroup\$ Really nice. +1 \$\endgroup\$Mr.Wizard– Mr.Wizard2013年01月13日 06:54:52 +00:00Commented Jan 13, 2013 at 6:54
GolfScript, (削除) 112 (削除ここまで) 105 characters
3,21*{..+6rand<3*+)}%3/\{)\.+-1%>2<.p~<}+,,"User
Computer"n/111ドル<=" wins with "+\[.~22+]1ドル>~+" points"+
Run it online.
The script expects the input on STDIN and then prints the outcome of the dice rolls (first column computer, second user) and the final statistics to STDOUT.
Ruby 1.8, 165
i,s,*d=getc,21,[4]*5<<1,[3]*5<<6,[2,5]*3
puts"#{s.times{p r=[i,i-1].map{|o|d[o%3][rand 6]};s+=r[0]<=>r[1]}>s?"Human":"Computer"} wins with #{[s/=2,21-s].max} points"
getc gets the ascii value of the input (ruby 1.8 only), which happily is congruent modulo 3 to its integer value.
s starts out at 21, so s.times{code} will execute code 21 times and return 21. On each iteration, the loop either adds or subtracts 1 from s depending on who wins, so we can see who won by seeing whether s has ended up below 21. Neat so far, but then I need the clumsy expression [s/=2,21-s].max to extract the actual number of points. I've long wanted to do arithmetic with the return value of <=>, so I'm happy anyway.
Mathematica (削除) 234 (削除ここまで) 247
Code
g@n_ := {t = RandomChoice[{{5, 25, 1, 5}/36 -> {{3, 1}, {3, 4}, {6, 1}, {6, 4}},
{5, 1, 5, 1}/12 -> {{2, 3}, {2, 6}, {5, 3}, {5, 6}},
{1, 1, 5, 5}/12 -> {{1, 2}, {1, 5}, {4, 2}, {4, 5}}}[[n]], 21],
Row[{If[(c = Count[t, {x_, y_} /; y > x]) > 10, "Computer ", "Player "],
"wins with ", If[c > 10, c, 21 - c], " points"}]}
Usage
{Player's roll, Computer's roll}
g[1]
g[2]
g[3]
results
Explanation
n is the number 1, 2, or 3 that corresponds to the die of the player.
Because n also determines (but does not equal) the die of the computer, we can generate all possible rolls of the dice when n=1, n=2, n=3. We can also determine their respective probabilities.
Examine the data right after RandomChoice:
{5, 25, 1, 5}/36 -> {{3, 1}, {3, 4}, {6, 1}, {6, 4}}
If the player draws die 1, the only possible outcomes are the following 4 pairs
{{3, 1}, {3, 4}, {6, 1}, {6, 4}}
The respective probabilities of these pairs are
{5, 25, 1, 5}/36, that is,
{5/36, 25/36, 1/36, 5/36}
RandomChoice[<data>, 21] outputs 21 rolls of the two dice.
C, (削除) 205 (削除ここまで) 191
p;r(c){return 1+c+3*(rand()%6>2*c);}main(i,c,q,s){for(c=51-getchar();++i<23;printf("%u %u\n",q,s))q=r(c),p+=(s=r(-~c%3))<q;printf("%ser wins with %u points",p<11?"Comput":"Us",p<11?21-p:p);}
Reads the user's choice from stdin.
-
\$\begingroup\$ Some tips:
for(c=51-getchar(p=0);,printf("%ser wins), reorder expression inrto start with(and save space. \$\endgroup\$ugoren– ugoren2013年01月09日 07:50:02 +00:00Commented Jan 9, 2013 at 7:50 -
\$\begingroup\$ And more:
(c+1)%3->-~c%3, makepstatic (initialized to 0), remove{}afterfor(;->,within them), usep<11?:twice withinprintfinstead of assigningp,q. \$\endgroup\$ugoren– ugoren2013年01月09日 08:37:01 +00:00Commented Jan 9, 2013 at 8:37 -
\$\begingroup\$ And you can set
s,qin the loopprintf, and incrementpafterwards, thus saving parentheses. Also change thecassignment to use%3or%7, giving a different order of 0,1,2. \$\endgroup\$ugoren– ugoren2013年01月09日 15:36:46 +00:00Commented Jan 9, 2013 at 15:36
Factor
With includes: 388
Without: 300
USING: arrays formatting io kernel math math.parser prettyprint random sequences ;
IN: N
CONSTANT: d { { 3 3 3 3 3 6 } { 2 2 2 5 5 5 } { 1 4 4 4 4 4 } }
: p ( -- ) 1 read string>number [ 3 mod 1 + ] keep [ 1 - d nth ] bi@ 2array 21 iota [ drop first2 [ random ] bi@ [ 2array . ] 2keep < ] with map [ ] count [ 11 > "Comput" "Play" ? ] [ "er wins with %d points" sprintf ] bi append print ;
Yeah, Factor's not really the language to use when golfing, but it's nice.
Python 182
from random import*
u=2+input()
r=[eval("int(choice(`0x1d67e987c0e17c9`[i%3::3])),"*21)for i in(u,u-1)]
U,C=map(sum,r)
print r,['Us','Comput'][U<C]+'er wins with %d points'%abs(U-C)
R 206
u=scan()
D=list(c(rep(3,5),6),c(2,5),c(1,rep(4,5)))
S=sample
U=S(D[[u]],21,T)
C=S(D[[(u+1)%%3+1]],21,T)
print(cbind(U,C))
W=sum(U>C)
I=(W>10)+1
cat(c("Computer","User")[I],"wins with",c(21-W,W)[I],"points")