This puzzle came up in the New York Times Number Play blog. It goes like this:
An entrepreneur has devised a gambling machine that chooses two independent random variables x and y that are uniformly and independently distributed between 0 and 100. He plans to tell any customer the value of x and to ask him whether y > x or x > y.
If the customer guesses correctly, he is given y dollars. If x = y, he’s given y/2 dollars. And if he’s wrong about which is larger, he’s given nothing.
The entrepreneur plans to charge his customers $40 for the privilege of playing the game. Would you play?
I figured I’d give it a go. Since I was feeling lazy, and already had my computer in front of me, I thought that I’d do it via simulation rather than working out the exact maths. I tried playing the game with the first strategy that came to mind. If x<50, I would choose y>x, and if x>50, I’d choose y<x, figuring I’d maximize my probability of winning something rather than nothing. This was probably due to the inherent risk aversion of system one. Let’s see how that works out:
N<-100000 x<-sample.int(100,N,replace=TRUE) y<-sample.int(100,N,replace=TRUE) dec_rule=50 payout<-numeric(N) for(i in 1:N) { ## Correct Guess (playing simple max p(!0) strategy) if( (x[i]>dec_rule & y[i]<x[i]) | (x[i]<=dec_rule & y[i]>x[i]) ) payout[i]<-y[i] ## Incorrect Guess (playing simple max p(!0) strategy) if( (x[i]>dec_rule & y[i]>x[i]) | (x[i]<=dec_rule & y[i]<x[i]) ) payout[i]<-0 ## Tie pays out y/2 if(x[i] == y[i]) payout[i]<-y[i]/2 } ## Expected Payout ## print(paste(dec_rule,mean(payout)))
Which leads to an expected payout of $37.75. Playing the risk averse strategy leads to an expected value less than the cost of admission, loosing on average 25 cents per play. No deal, Mr entrepreneur, I had something else in mind for my forty bucks anyway.
Lets try alternate strategies, and see if we can’t play in such a way as to improve our outlook.
## Gambling Machine Puzzle ## ## Puzzle presented in http://wordplay.blogs.nytimes.com/2013/03/04/machine/ result<-numeric(100) for(dec_rule in 1:100) { N<-10000 x<-sample.int(100,N,replace=TRUE) y<-sample.int(100,N,replace=TRUE) payout<-numeric(N) for(i in 1:N) { ## Correct Guess (playing dec_rule strategy) if( (x[i]>dec_rule & y[i]<x[i]) | (x[i]<=dec_rule & y[i]>x[i]) ) payout[i]<-y[i] ## Incorrect Guess (playing dec_rule strategy) if( (x[i]>dec_rule & y[i]>x[i]) | (x[i]<=dec_rule & y[i]<x[i]) ) payout[i]<-0 ## Tie pays out y/2 if(x[i] == y[i]) payout[i]<-y[i]/2 } ## Expected Payout ## print(paste(dec_rule,mean(payout))) result[dec_rule]<-mean(payout) } par(cex=1.5) plot(result,xlab='Decision rule',ylab='E(payout)',pch=20) abline(v=which.max(result)) abline(h=max(result)) abline(h=40,lty=3)
According to which, the best case scenario is an expected payout of $40.66, or an expected net of 66 cents per bet, if you were to play the strategy of choosing y>x for any x<73 and y<x for any x>73. You’re on, Mr entrepreneur!
To calculate the exactly optimal strategy and expected payout, we would need to compute the derivative of the expected payout function with respect to the within game decision threshold. I leave this fun stuff to the reader 😉
I was stuck on a bus so I worked out the math on this one. (Someone should comment if they noticed a more elegant way of solving). (Everything is divided by 100).
First I tried to find the decision rule for when to choose y>x. Given x, the payout if you choose y>x is intergral from y=x to 1 of ydy. This is equal to (1/2 – x^2/2). If you choose x>y, then you get integral from y=0 to x of ydy. This is equal to x^2/2. If you plot these equations you’ll see that you should choose y>x for any value of x y + your payoff when you choose y>x).
The two parts are equal to 37/384 + 39/128. This comes to 0.40104, a slight edge to the bettor.
I don’t understand the sentence starting with: “If you plot these equations you’ll see that you should choose y>x for … )”.
I think something disappeared here; there is at least a closing ) without a matching opening (.
People often behave as if they care about regret and not about results. In light of this, I changed the payout to 0 when making the right decision and to the lost money when making the wrong decision.
Recalculating, the best decision becomes choosing y, whenever x < 58.
This should be closer to how people really behave (and should behave, if they only care about minimizing 'regret').
Having read something somewhere about decision rules, I get the feeling that this solution comes from the evaluation of (100/e)*2, but I’m not so sure why….
Just a thought.
The performance (speed) of the simualtion can be improved by using vectorised if (although in this case the penalty for using a loop is trivial):
payout = ifelse(x > dec_rule,
ifelse(y x, y, 0) # Low x wins
)
payout = ifelse(x == y, y/2, payout) # Ties
Cheers.
Grr – the angle brackets are bieng swallowed into the html. One day I might learn how to post these comments legibly. Psuedo R follows:
payout = ifelse(x gt dec_rule, ifelse(y lt x, y, 0), ifelse(y gt x, y, 0) )
payout = ifelse(x == y, y/2, payout.vec)
This is getting ridiculous…
“payout.vec” should be “payout”
Thanks for that. I usually code with loops first then go back and vectorize if performance is an issue. Just a vestigial habit from c++ programming.
Pingback: Solution to the gambling machine puzzle | God plays dice
Reblogged this on lava kafle kathmandu nepal.
Pingback: bayesianbiologist
Pingback: Somewhere else, part 38 | Freakonometrics
I perform agree tough ideas you’ve got presented as part of your post. Theyre truly convincing and will definitely perform. Still, the posts are very short for newbies. Could you please expand them a bit from next occasion? Thanks to the post.
Thanks a lot for this post. Exciting little game. I’m currently learning R (and coding for that matter), and I tried to adapt your loop to work over the reals on [0,100] instead of the integers. I wonder if you would look at my code and tell me if it’s working properly or if I messed up somewhere. Thanks a lot.
http://pastebin.com/HWvFsfjJ
Feel free to use it or parts of it by the way.
I think that having the set.seed() inside that loop will give you problems since this will have the effect that the same series of outcomes will occur across all decision cutoffs.
Good job!
That’s what I did.
N<-100000
x<-sample.int(100,N,replace=TRUE)
y<-sample.int(100,N,replace=TRUE)
expected<-rep(NA,101)
for (cutoff in 0:100)
{
expected[cutoff]=cutoff)==(x>y))&(x!=y))*y+(x==y)*y/2)
}
plot(expected)
The result is identical.
x<-sample.int(101,N,replace=TRUE)-1
y=1.
Vectorize all the things!! That’s much faster. Thanks, David!