A few weeks ago, I watched an episode of Numberphile about the Monty Hall problem. This happens to be one of my favorite little “that-doesn’t-seem-right” statistics things, and I thought it would be a great way to play with Python.
The Problem
If you’re not familiar with the Problem, here’s the gist of it. There are three doors and you’re asked to pick one of them. Now, behind one door is an amazing prize: a new car, a bunch of money, a trip to a tropical island. You get the idea. Behind the other two doors, though, there’s something useless or just nothing. Maybe it’s a goat. Regardless, you don’t want what’s behind those other two doors.
So you pick your door and the host, Monty Hall, opens one of the two doors you didn’t pick. It’s always one of the horrible non-prizes. And now comes the stressful part of the game: Monty asks if you’d like to switch doors. Do you stick with the door you picked in the beginning or do you switch to the new door?
Our Python Classes
While you think about that, let’s get to the code. We need a couple of things set up before we can play the game. Mostly, though, we need a door.
class Door(object):
prize = False
opened = False
So, OK, here’s our door. By default, it’s closed (opened = False
) and it doesn’t have a prize. Since we’ll make multiple doors for a game, I think it makes more sense to have the game pick which door has the prize than it does for the doors to decide for themselves. No one wants a sentient door.
Speaking of our game, let’s look at that object too.
class Game(object):
chosen_door = None
switched_doors = False
def __init__(self):
self.doors = [
Door(),
Door(),
Door()
]
# Pick a random door and give it a prize
random.choice(self.doors).prize = True
We start with no doors chosen and, of course, since no doors have been chosen, the player couldn’t possibly have switched doors. Then we create three doors and randomly pick one of them to have a prize. We’re all set up to play the game.
The Whole Game
Here’s a gist of the entire game:
The way it’s set up, you can just call Game.play()
however many times you want to play the game. I found that playing it a small number of times, say 10–50, doesn’t yield any noticeable results but bump the number up into the hundreds or thousands and you start to see real answers.
For example, here’s what I’ve gotten when I run it:
Won & Switched | Won & Stayed | Lost & Switched | Lost & Stayed |
---|---|---|---|
340 | 178 | 170 | 312 |
322 | 194 | 162 | 322 |
329 | 161 | 190 | 320 |
317 | 160 | 187 | 336 |
337 | 167 | 186 | 310 |
While this is only the results of running the script 5 times, you can see that it’s generally a 2:1 ration of winning when the player switches compared to winning when they don’t switch.
Takeaways
My script is pretty simple. You could easily change this to have more doors or to take user input on whether or not to switch. You could also use the handy plotting techniques from Data Science Basics to make a chart showing wins and loses, switches and stays. Oh, and if the list comprehensions and uses of filter
and lambda
are confusing, we have a couple of workshops on those you should check out. All of the code in the gist should run in both Python 2 and Python 3.
So, what’s your decision? Will you switch doors or stick with the one you have?
Photo by Frank Müller