## A Python simulation of Monty Hall problem

Published in

·

6 min read

·

Jun 26, 2021

--

Monty Hall problem is a mathematical brain teaser dealing with probabilistic decision making. It originated from a TV show hosted by Monty Hall in 1963. It is a very good example of how probabilistic scenarios may seem simple but yet at times can be difficult to wrap our minds around them.

The problem is simple, you go to Monty’s game show “Let’s make a deal”. There are 3 doors in front of you. Behind 1 of those doors, there is a car and behind the remaining two doors are goats! If you select the door behind which the car is there, you drive it home. The host asks you to select a door, you pick one. Then comes the fun part. After you picked a door, the host will open one of the two remaining doors to **always** reveal a goat. Now he would ask you, are you going to switch your selection or are you staying with your original choice? This is where the dilemma kicks in.

On the surface, it seems there is no clear advantage in staying with your original decision or switching it. Since there are now two unopened doors, we see it as a 50–50 choice. But in fact, if you ponder enough you will see that there is a clear advantage of changing your decision when the host asks you whether you wanna switch!!!

The key reason this is not a 50–50 scenario is that the host, who opens one of the remaining doors **after you made** your initial choice, has the information that you don’t — which door has the car behind it. And he **never** opens the door which has the car behind it. If we incorporate this piece of information into calculating the probabilities, we end up with the number that you have a 2/3 probability of winning if you switch.

There are a lot of good explanations using multiple methodologies on the internet. (I find this, that and the other one to be interesting.) But personally, I feel, in probability, anything can be simply and intuitively explained using a tree diagram.

When you are asked to make your first choice, there is an equal probability that the car is behind any one of the three doors. So you have a 1/3 chance of guessing it correctly. This implies that 2/3 of the times your guesses are wrong. So now comes the host and he opens a door to reveal a goat. At this point his choice of opening a door is not random. It is governed by your previous choice, since he has a rule not to reveal the car when opening the door.

Let’s first consider the case where your first choice is correct. Then the remaining two doors have goats behind them. In this scenario, the host can open any of those two doors. So now if you change your initial choice you will definitely loose regardless of the host’s choice of door. But remember this happens only 1/3 of the times because your initial choice is only correct that many times.

Now consider the case when your initial choice is wrong. You choose a door behind which a goat is there. Now out of the two remaining doors, one has the car behind it, and one has a goat behind it. Now the host cannot open a door randomly. He cannot open the door with the car behind it. So he is **forced** to open the door with the other goat behind it. At this point, if you change your initial choice, you’ll definitely win. If we look back to initial probabilities, we can realize that this is the most likely scenario, since 2/3 of the times our initial guess is wrong. So you should always make the switch! Statistically, if you play this game infinitely many times you will win in 2/3 of the games you play, if you always make the switch.

I was discussing this with one of my friends and he was like, “yeah that seems understandable but it is still a bit dizzy to get a feel for this explanation”. So I thought, “Hey let’s simulate it and get the same number!”. That way, seeing empirical proof would be more convincing!

So let’s get to the fun part! I created the whole program with number of doors as configurable, so that if someone wants to simulate scenarios with more doors (as explained here), it can be done.

First, let’s look at the `Contestant`

class. It has one constructor parameter `switch`

. This parameter defines the response of the contestant when asked “Do you wanna switch?”. By changing this parameter when instantiating the contestant object, we can simulate a contestant who always switches and a contestant who never switches.

The `Contestant`

class has two methods. The first one is `select_door()`

. This is used to make the initial choice. When given the number of doors (`door_count`

) as input, it selects and returns one door (`selection`

) with a random uniform probability. Next method is `wanna_switch()`

. This method is to be invoked when the host opens all remaining doors, presents one alternative door, and asks the contestant if she/he wants to change her/his decision? It takes one input: the `new_door`

. If the contestant’s attribute `switch`

is `False`

, this method returns the old `selection`

(sticking with the original decision). If the contestant’s attribute `switch`

is true, it returns the `new_door`

(changing the original choice).

Next we have the `Host`

class. It takes one constructor parameter `door_count`

. During instantiation the `Host`

class randomly ‘places’ the imaginary car behind one of the doors by setting the private attribute `_car_index`

. *I have made the **_car_index**, **door_counts** attributes of the **Host** class, since the host has knowledge of these.*

The `Host`

class has three methods. The first one is `present_doors()`

, which is used to show the doors to the contestant by returning the `door_count`

. The next method is `eliminate_others_and_present_one_door()`

. This method takes the contestant’s first selection (`contestant_selection`

) as an input and returns an `alternative_door`

as output, to ask the contestant whether she/he wants to switch? If the contestant's first selection is the door with the car behind it, it randomly returns another door as `alternative_door`

. If the contestant’s first choice is not the door with the car behind it, this method returns the `_car_index`

(door with the car behind it) as `alternative_door`

. (*This returning of **alternative_door** is analogous to opening all other doors and revealing goats behind them.*) The final method is `reveal_if_winner()`

. It takes the contestant’s `final_selection`

as the input and returns if the contestant has won or not.

Putting everything together we can simulate one iteration of the competition using the snippet shown below.

However to get the actual probability of winning we need to simulate this infinitely many times (which is impossible). Hence I have simulated this for 1 million times and used the resulting number as a proxy to actual probability. As we increase the number of iterations, we can see in fig. 2, that the empirical probability is converging towards the (expected) actual probability.

I have simulated two contestants: one who always changes her/his decision and one who always sticks with the original decision. From the above results, we can clearly see, that if we switch our decision when asked, we have a better chance of driving the imaginary car home.

Safe driving… 😁

In case if you want to access the full code (I don’t know why someone would want that), it can be found here.

“Numberphile” explanation video — https://www.youtube.com/watch?v=4Lb-6rxZxx0

“The Infographics Show” explanation video — https://www.youtube.com/watch?v=hdo4CZC76fA