Yahtzee in Mathematica

Rules of Yahtzee (simplified)

Roll five dice, and re-roll some of them until all five dice show the same number.

Roll five dice. Suppose you get 1, 2, 1, 3, 1.

Keep the values that occur the most. In this example, we have three 1s.

Re-roll the other dice. In this case, re-roll the two dice that are not 1s. Suppose you get 1 and 4.

Repeat. In this example, we now have 1, 1, 1, 1, 4. Re-roll the die that isn’t a 1 until it shows a 1.

Simulating Yahtzee

First, break the problem into smaller pieces and write code for each.

To simulate rolling a die, use the RandomInteger function:

RandomInteger[{1,6}]

RandomInteger can also roll many dice at once:

RandomInteger[{1,6},5]

We can write our own function to make this a bit easier to use:

rollDice[n_]:=RandomInteger[{1,6},n]

Try it out:

currRolls=rollDice[5]

Next, we need to count the number of 1s, 2s, ..., 6s that appear in currRolls. Store these counts in a list called counts.

counts=Table[ Count[currRolls,i], {i,1,6} ]

Now we need to find the largest number in our list counts, as well as which number on the dice was the most common roll.

maxCount=Max[counts] (* number of times the most common roll appears *)

We can use Position to find the value of the most common roll, but it’s returned in a nested list:

Position[counts,maxCount]

We get the value out of the nested list like this:

maxVal=Position[counts,maxCount][[1,1]] (* number of the most common roll *)

Now keep only the matched dice. We can simply reconstruct matchedRolls to be a list of length maxCount, with each list element equal to maxVal.

matchedRolls=Table[maxVal,maxCount]

If all dice don’t show the same number, then re-roll the non-matching dice.

currRolls=Join[matchedRolls,rollDice[5-Length[matchedRolls]]]

At this point, we want to again count the number of matched dice, re-roll the unmatched dice, etc. We could re-run the lines of code above that does that. However, a more elegant solution is to write a loop that rolls the dice, counts matches, and re-rolls as many times as necessary until all five dice show the same number. We’ll do that in the next section.

Completing the Yahtzee simulation in a module

Now we will copy the code we wrote above and put it in a loop. The loop will run until all five dice match. We will use a variable called numRolls to keep track of how many times we roll the dice until all dice match. We will package all of this in a module so that we can run it easily. The module will return the number of rolls.

rollYahtzee:=Module[{numRolls=0,matchedRolls={},k,currRolls,counts,maxCount,maxVal},
While[Length[matchedRolls] < 5,
(* roll k dice and join their values to matchedRolls *)
k = 5 - Length[matchedRolls];
currRolls = Join[matchedRolls,rollDice[k]];

(* increment numRolls *)
numRolls+=1;

(* testing only: *)
Print[currRolls]; 

(* find the most common roll *)
counts=Table[ Count[currRolls,i], {i,1,6} ];
maxCount=Max[counts]; (* number of times the most common roll appears *)
maxVal=Position[counts,maxCount][[1,1]];(* value of the most common roll *)

(* keep only the matched dice *)
matchedRolls=Table[maxVal,maxCount]
];

(* now all 5 dice show the same value, so return numRolls *)
numRolls
]

Try it out:

rollYahtzee