//ShakeOTheDay.java
import java.util.*;
/**
* A program to calculate the probability of winning the "Shake
* of the Day" dice game at a certain watering hole in Madison,
* Wisconsin (using Monte Carlo methods). It turns out to be a
* hard problem for statistically unsophisticated bar-goers to
* solve analytically because, as in Yahtzee, you can save dice
* that match the number of the day in each roll (and only reroll
* the remaining dice). This program was written to finally put
* to rest an ongoing argument over whether or not it was
* advantageous (from a "pot odds" perspective) to play the game,
* given some known jackpot size (which of course isn't known
* exactly in practice, but you can estimate by looking at the
* jar they keep the money in).
*
* Rules: You get three rolls to achieve a "Yahtzee" on whatever
* Shake of the Day number happens to be posted (here we chose 5,
* which was the number on the day we actually wrote the thing).
* After each roll, you can save any nice that match the goal
* and just reroll the remainging ones.
*
* Assumptions: In reality, you get two shakes for a dollar and
* can purchase an additional shake for an extra dollar. We
* assumed a pure strategy where you always choose to make
* _either_ two or three rolls.
*
* Interpretation: If you run the code, you'll find that
* (for a sufficiently large value of numTries), the probability
* of winning if you never buy the extra roll is 0.25%, which
* means you should only play if theres ~400 bucks in the pot.
* If you always buy the extra shake, the odds go to 1.33%, so
* it's worth playing if there's $150 or so in the pot.
*
* Interesting psychological observation: Kyle has never played
* this game, even when the pot appears to be large enough to
* make it worth the risk. Matt continues to play it, even when
* there's clearly not $150 to be won.
*
* Disclaimer: We wrote this code just for fun, and it shouldn't
* be interpreted as formal advice for playing "Shake of the Day"
* or as a statement about the fairness of the game. Who cares?
* It's just a dice game in a bar. Also, I realize this
* implementation isn't especially efficient (my roommate wrote
* another version in way fewer lines that performs a lot better).
* But I'm a modeler, and I was in a data structures class at the
* time, both of which are factors in the way I went about writing
* this thing.
*
* Written by: Kyle Oliver
*
* Enjoy!
*/
public class ShakeOTheDay {
static boolean youWin = false;
public static void main(String [] args) {
Random rand = new Random();
int key = 5;
int numTries = 10000000;
int numWins = 0;
int numShakes = 3;
for (int i = 0; i < numTries; i++) {
int[] bar = {0, 0, 0, 0, 0};
int rollsLeft = numShakes;
while (rollsLeft > 0) {
bar = shake(bar, key, rand);
// see if we won yet
int numYouNeed = 5;
int numYouHave = 0;
for (int j: bar) {
if (j == key) {
numYouHave ++;
}
}
if (numYouNeed == numYouHave) {
ShakeOTheDay.youWin = true;
}
rollsLeft --;
}
if (ShakeOTheDay.youWin == true) {
numWins ++;
}
ShakeOTheDay.youWin = false;
}
double totalWins = numWins;
double percentage = totalWins / numTries * 100;
System.out.println("The odds of winning with " + numShakes + " shakes are " + percentage +
"% (n = " + numTries + ").");
}
private static int rollDie(Random rand) {
return rand.nextInt(6) + 1;
}
private static int[] shake(int[] bar, int key, Random rand) {
for (int i = 0; i < bar.length; i++) {
if (bar[i] == 0) {
int roll = rollDie(rand);
if (roll == key)
bar[i] = roll;
}
}
return bar;
}
}