Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

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.

share|improve this question

10 Answers 10

up vote 1 down vote accepted

GolfScript, 112 105 characters

3,21*{..+6rand<3*+)}%3/\{)\.+-1%>2<.p~<}+,,"User
Computer"n/1$11<=" 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.

share|improve this answer

APL (106 114)

'Computer' 'User'[1+X],'wins with','points',⍨|Z-21×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 vector 1 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: set X to whether the user won (if 11 is higher than the computer's score).
  • 'Computer' 'User'[1+X]. X is whether the user won.
  • 'wins with','points',⍨|Z-21×X: Z is the computer's score, so if the computer won display Z, otherwise display 21-Z.
share|improve this answer
    
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. –  TwiNight Jan 10 '13 at 22:03
    
@TwiNight: fixed it –  marinus Jan 11 '13 at 18:32
    
Negative points when user wins. You can fix by |Z-21×X which doesn't change char count –  TwiNight Jan 11 '13 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
share|improve this answer
    
You can replace summary.factor with table, saving 9 characters. –  Brian Diggs Apr 7 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]}}] &
share|improve this answer
    
I think the output is supposed to list the values of each roll of the dice. –  David Carraher Jan 10 '13 at 1:45
    
@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. –  belisarius Jan 10 '13 at 2:25
    
It now seems to be working fine. –  David Carraher Jan 10 '13 at 3:28
    
@dude Much better now –  belisarius Jan 10 '13 at 20:16
    
Really nice. +1 –  Mr.Wizard Jan 13 '13 at 6:54

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.

share|improve this answer

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.

share|improve this answer

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.

share|improve this answer
    
Some tips: for(c=51-getchar(p=0);, printf("%ser wins), reorder expression in r to start with ( and save space. –  ugoren Jan 9 '13 at 7:50
    
And more: (c+1)%3 -> -~c%3, make p static (initialized to 0), remove {} after for (;->, within them), use p<11?: twice within printf instead of assigning p,q. –  ugoren Jan 9 '13 at 8:37
    
And you can set s,q in the loop printf, and increment p afterwards, thus saving parentheses. Also change the c assignment to use %3 or %7, giving a different order of 0,1,2. –  ugoren Jan 9 '13 at 15:36

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)
share|improve this answer

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.

share|improve this answer

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")
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.