Scripting The Monty Hall Problem
Tags: python, programming, sideprojects, beginners
Published: 2021-11-08 06:08:26

Ahoy!

If like me your eyes glisten and your ears perk up when you come across deceptive math puzzles, you are sure to find some value in this piece. Here, I introduce the Monty Hall problem, discuss a useful way to think about the solution, and present a python script I wrote to validate it.


<h2>The Monty Hall Problem</h2>
The Monty Hall problem (named after Monty Hall, a game show host) is a rather deceptive brain teaser that became somewhat popular towards the end of the 20th Century. It is not a difficult problem to understand as it contains very simple premises but it is, nevertheless, pretty tricky to solve. 

Like the Ball And Bat Problem, psychologists often use the Monty Hall problem to illustrate how easily humans can fail to grasp the "math" or the "rational", opting instead for the "immediately obvious" or "intuitive" response. They call out our tendency to introduce bias and other forms of heuristics when making decisions—preferring easier, less laborious, and inaccurate approaches to more tasking, and more accurate ones. 

What I find most amusing and fascinating about such problems that is that we are usually very aware that they are tricky problems—tricky problems that we are probably hearing about because they've most likely conquered the minds of many people. Yet, we dive in to answer them, optimistic that we'd give a correct response. But of course, we are usually wrong—like I and most people were with the Monty Hall Problem. And even when we are presented with the correct answer, it could be pretty difficult to wrap our heads around the right answer.

The Monty Hall problem tests our understanding of probabilities in some sort of illusory manner. Here is my  variant of the problem:

Say you are Luffy, a pirate searching for the grandest treasure—The One Piece. Say there are three identical maps, one of which leads you to the treasure. The other two maps lead you to a wasteland filled with sand. Of course you want the treasure, but you don't know which of the three maps has the treasure. You can't differentiate one from the other.

Say the maps have a custodian, Monty Hall, and he knows what map leads where. In other words, Monty Hall knows which maps lead you to a wasteland and the one that can guide you to the treasure. He decides to play a game with you as follows;

- You are to pick any one of the three maps (at this point, you don't know if your chosen map leads you to the treasure or to a wasteland)
- Next, of the other two maps, Monty Hall picks one map that leads to a wasteland. Remember, he knows where each map leads to and he always picks a wasteland map.
- At this point you have picked one map (that may or may not lead to the treasure) and Monty Hall has picked a map that definitely leads to the wasteland. Monty's map needn't be considered anymore, but there is a third map that neither of you chose.
- Next, Monty Hall asks you; do you want to stick with your initial selection or do you want to switch your selection to the third map?

That's the problem statement. You are given a choice to stick with your initial map selection or switch to the third map that neither of you chose. Will you stick or switch?

![Luffy befuddled](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jlgj5nyus9f3cmo7nacz.png)

<h2>The Answer</h2>
With little or no deliberation, we are tempted to choose to stick with our original decision. This is because we believe that switching to the third map would not change the odds that we chose the right map. Our mind is heavily focused on the probability that our first choice was correct, and switching seems like an unnecessary risk. We could also think, perhaps, that after that after Monty Hall chooses the second map, the probability that our original selection is the treasure map is equal to the probability that the third map is the treasure map, i.e. 1/2 each since there are now two options. So there is no point switching. But that is not so!

It may take some time to sink in, but here is what I consider a useful approach to analysing the problem;

At the start, when you make the first selection 
- the probability of picking a treasure map is 1/3;
- and the probability of picking a wasteland map is 2/3

In other words, you are more likely to pick a wasteland map than a treasure map.

Next, regardless of your choice, Monty Hall will always pick a wasteland map. 

After Monty picks, there are two possible scenarios; either the third unselected map is the treasure map or it is another wasteland map. And these two scenarios play out probabilistically in relation to your first choice in the following ways;
- if the third unselected map is a wasteland map, it must mean that your first selection was the treasure map. This happens one-third of the time (1/3) as stated above. And therefore, you'd win if you don't switch
- if the third unselected map is the treasure map, it must mean that your first selection was a wasteland map. This happens two-thirds of the time (2/3) as stated above. And therefore, you'd win if you switch

As such, since your first selection is likely to be a wasteland map than the treasure map, it makes statistical sense to always switch to the third map. Of course, winning is not guaranteed by switching. But you are twice as likely to win when you switch than when you stick to your first selection. So always switch!

## The Python Script: Some Evidence
It is normal to still have doubts about the solution to the Monty Hall problem. A useful way to perhaps, cement your belief in and acceptance of the answer is to simulate the problem several times. This is exactly what I did with using a Python Script. You can find the gist [here](https://gist.github.com/Wolemercy/3d26cb6ad5b9a9c18a819121e78b0346) and the repo [here](https://github.com/Wolemercy/monty-hall).

{% gist https://gist.github.com/Wolemercy/3d26cb6ad5b9a9c18a819121e78b0346 %}

Let's walk through the code;

First we import the `random` module. We define a function called `single run` that initializes our map trio as an array. We select a random map to contain our One Piece treasure and the function returns the map array.

```
# The Monty Hall Problem

import random

# Instantiating a random treasure map
def single_run():
    maps = ['wasteland', 'wasteland', 'wasteland']
    treasure_index = random.randint(0, 2)
    maps[treasure_index] = 'one piece'
    return maps
```

Next, we define a function that returns Luffy's random first choice

```
# Luffy's first choice
def luffy():
    luffy_first_choice = random.randint(0, 2)
    return luffy_first_choice
```

Next, we define a function that returns Monty's choice of a wasteland map. We use a while loop to ensure that Monty's chosen map is neither Luffy's first choice nor the treasure map.

```
# Monty's choice of a location that is neither Luffy's choice nor the treasure location
def monty(maps, luffy_first_choice):
    monty_choice = 0

    while monty_choice == luffy_first_choice or maps[monty_choice] == 'one piece':
        monty_choice += 1
    
    return monty_choice
```

Next we define a function that returns Luffy's switched choice. Note that this function is not necessary for the simulation. I only included it for the sake of completeness. 

```
# switch Luffy's choice
def luffy_switch(luffy_first_choice, monty_choice):
    
    luffy_switch_choice = 0

    while luffy_switch_choice == luffy_first_choice or luffy_switch_choice == monty_choice:
        luffy_switch_choice += 1

    return luffy_switch_choice
```

Next, we define a function that returns the output. It accepts as input, the number of times switching yielded the treasure map, the number of times sticking yielded the treasure map, and the number of trials. It returns the percentages for both decisions as part of a string.

```
# output to be displayed
def output(stick, switch, trials):
    stick_percent = round((stick/trials) * 100)
    switch_percent = round((switch/trials) * 100)
    
    print(f'Luffy found One Piece {stick_percent} % of the time when he decided to stick to his initial choice ')
    print(f'Luffy found One Piece {switch_percent} % of the time when he decided to switch his initial choice')

```

And we have the body of the script. It accepts the number of trials as input, i.e. the number of simulations you want to run. We also initialize the number of  times sticking and switching yield the treasure map to zero. 

We run our loop as many times as the number of trials. Inside the  loop, we use are already defined functions to;
- get the maps array
- randomly make Luffy's initial map choice
- make Monty choose a wasteland map
- switch Luffy's initial choice
- increment the `stick_count` if the initial choice has the One Piece treasure
- increment the `switch_count` if the switched choice has the One Piece treasure

```
print('The Monty Hall Problem')
trials = int(input('Enter the number of trials:  '))

# Luffy sticks
stick_count = 0

# Luffy switches
switch_count = 0

for i in range(trials):
    maps = single_run()
    luffy_first_choice = luffy()
    monty_choice = monty(maps, luffy_first_choice)
    luffy_switch_choice = luffy_switch(luffy_first_choice, monty_choice)

    if maps[luffy_first_choice] == 'one piece':
        stick_count += 1
    
    elif maps[luffy_switch_choice] == 'one piece':
        switch_count += 1

output(stick_count, switch_count, trials) 
```

Note, as mentioned earlier, that we don't need the `luffy_switch` function, and by implication we can do without incrementing the `switch_count` as we have done. That's because we are  sure that if Luffy's initial choice was the treasure map, then the third choice is definitely not the treasure map. In the same vein, if Luffy's initial choice wasn't the treasure map, then the third choice that could have been switched to would be the treasure map. 

In other words, the treasure map is either the original choice or the switched choice. The incidences of both (`stick_count` and `switch_count` ) necessarily add up to the number of trials. So we can use simple arithmetic to evaluate one if we have the other; `switch_count = trials - stick_count`. That's definitely a more concise way of writing this script. I only wrote it this way for the sake of completeness.


## Conclusion
The result of running the Python Script (several times) proves that Luffy gets the treasure map about two-thirds (2/3) of the time when he switches as opposed to one-third (1/3) of the time when he sticks with his original choice.

![Monty Hall script terminal output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mx4egob8t1vhoyg2igb6.png)

And that's The Monty Hall Problem. The key thing to remember is to always switch maps after Monty Hall chooses a wasteland map because your initial choice was more likely wrong than correct. As such, switching improves the chances that you'd win the treasure map. 

And when you find the treasure, remember to share it with me! A comment, a like, a repost, some feedback—anything will do!

Thanks for reading!
Also connect with me:
- LinkedIn: [Wolemercy](https://www.linkedin.com/in/wolemercy)
- Twitter:  [Wolemercy](https://twitter.com/wolemercy)
- GitHub: [Wolemercy](https://github.com/Wolemercy)