# Monty Hall Simulation Problem

**URL:** <https://discourse.processing.org/t/monty-hall-simulation-problem/31481>\
**Category:** Processing.py\
**Created:** [July 29, 2021, 6:38am UTC](https://discourse.processing.org/t/monty-hall-simulation-problem/31481 "2021-07-29T06:38:34Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![adisharma](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/adisharma/32/10680_2.png) [@adisharma](https://discourse.processing.org/u/adisharma)\
**Post date:** [July 29, 2021, 6:38am UTC](https://discourse.processing.org/t/monty-hall-simulation-problem/31481/1 "2021-07-29T06:38:34Z")

</div>

Hello Everyone, I am working on Monty Hall Simulation Problem Project and I am looking for source code. I have checked on github and found this [source](https://www.interviewbit.com/blog/python-projects/) but I want to know below code is optimize or not as a speed and size point of view?

```auto
import random
from tkinter import StringVar, Label, Tk, Entry

window = Tk()
window.geometry("400x100")
window.title("Monty hall simulation")
window.resizable(0, 0)

same_choice = StringVar()
switched_choice = StringVar()
same_choice.set(0)
switched_choice.set(0)
no_sample = Entry()
Label(text="Same choice").place(x=80, y=8)
Label(text="Switched choice").place(x=80, y=40)
Label(textvariable=same_choice, font=(15)).place(x=180, y=8)
Label(textvariable=switched_choice, font=(15)).place(x=180, y=40)
no_sample.place(x=100, y=70)

def simulate(event):
    same_choice_result = 0
    switched_choice_result = 0
    samples = int(no_sample.get())
    doors = ["gold", "goat", "bed"]
    for _ in range(samples):
        simulated_doors = doors.copy()
        random.shuffle(simulated_doors)
        first_choice = random.choice(simulated_doors)
        simulated_doors.remove(first_choice)
        opened_door = (
            simulated_doors[0] if simulated_doors[0] != "gold" else simulated_doors[1]
        )
        simulated_doors.remove(opened_door)
        switched_second_choice = simulated_doors[0]
        if first_choice == "gold":
            same_choice_result += 1
            same_choice.set(same_choice_result)
        elif switched_second_choice == "gold":
            switched_choice_result += 1
            switched_choice.set(switched_choice_result)
        else:
            print("That's will never happed")

no_sample.bind("<Return>", simulate)
window.mainloop()

```

---

<div class="post-metadata">

**Author:** ![TfGuy44](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/tfguy44/32/41_2.png) [@TfGuy44](https://discourse.processing.org/u/TfGuy44)\
**Post date:** [July 29, 2021, 7:31am UTC](https://discourse.processing.org/t/monty-hall-simulation-problem/31481/2 "2021-07-29T07:31:20Z")

</div>

That looks like python code. It may do what you want, but it being “optimized” is completely subjective.

You would be a lot better off if you wrote a version yourself. Then you would understand it a lot better…

---

<div class="post-metadata">

**Author:** ![javagar](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/javagar/32/11434_2.png) [@javagar](https://discourse.processing.org/u/javagar)\
**Post date:** [July 29, 2021, 8:04am UTC](https://discourse.processing.org/t/monty-hall-simulation-problem/31481/3 "2021-07-29T08:04:00Z")

</div>

The standard Monty Hall problem involves two goats and a car, with the car being the coveted prize. Given that, it is unclear why the example you found uses three different items here:

```auto
    doors = ["gold", "goat", "bed"]

```

See the following:

> **[Monty Hall problem](https://en.wikipedia.org/wiki/Monty_Hall_problem)**
>
> The Monty Hall problem is a brain teaser, in the form of a probability puzzle, loosely based on the American television game show Let's Make a Deal and named after its original host, Monty Hall. The problem was originally posed (and solved) in a letter by Steve Selvin to the American Statistician in 1975. It became famous as a question from reader Craig F. Whitaker's letter quoted in Marilyn vos Savant's "Ask Marilyn" column in Parade magazine in 1990:
> Suppose you're on a game show, and you'r...

The advice from @TfGuy44 is good. Discard the implementation from GutHub, study the standard version of the problem, and develop your solution from scratch.

Will you be using Processing Python Mode?

_EDITS (July 29 and 30, 2021):_

This is a very interesting problem that seems worthy of some experimentation, since according to the Wikipedia article cited above,

> … the correct choice (that one should switch doors) is so counterintuitive it can seem absurd, but is nevertheless demonstrably true.

Following are three simulations, each with a different user strategy. In all three cases, the host’s strategy is to follow the user’s first choice by opening a door with a goat behind it. If the user’s first choice has a car behind it, the host randomly chooses among the other two doors, with each having a goat. Otherwise, the user’s first choice has a goat behind it, and the host opens the single remaining door that also is backed by a goat.

The three user strategies in the simulations are:

- always stick with the first choice
- randomly decide whether to stick or switch
- always switch

Each simulation was run for 10,000 games.

The code is written for Python 3 with no `tkinter` or Processing Python Mode interface. @adisharma, I believe you would like a more graphical user interface than this, so this code probably does not satisfy your needs. However, you could opt for a similar algorithm.

Here’s the code:

```auto
import random

class MontyHallGame:
    def __init__ (self):
        self.doors = ["goat", "goat", "car"]
        random.shuffle(self.doors)
        self.available_choices = [0, 1, 2]
        self.first_user_choice = None # first door picked by user
        self.host_choice = None # door opened by host
        self.second_user_choice = None # second door picked by user
    def set_first_user_choice(self, door):
        self.first_user_choice = door
        self.available_choices.remove(door)
        for i in self.available_choices:
            if self.doors[i] == "car":
                self.available_choices.remove(i)
                break
    def get_first_user_choice(self):
        return self.first_user_choice
    def set_host_choice(self, door):
        self.host_choice = door
        self.available_choices = [0, 1, 2]
        self.available_choices.remove(door)
    def get_host_choice(self):
        return self.host_choice
    def set_second_user_choice(self, door):
        self.second_user_choice = door
    def get_second_user_choice(self):
        return self.second_user_choice
    def get_outcome(self):
        return self.doors[self.second_user_choice]
    def get_available_choices(self):
        return self.available_choices
    def get_doors(self):
        return self.doors

    # three user strategies for simulations
    # the host always chooses randomly among the two other doors
    # when user's first choice is the door with the car
    
    def play_random_game(self):
        # user randomly chooses from unopened doors for second choice
        self.set_first_user_choice(random.choice(self.get_available_choices()))
        self.set_host_choice(random.choice(self.get_available_choices()))
        self.set_second_user_choice(random.choice(self.get_available_choices()))
    def play_stick_game(self):
        # user always repeats first choice again as second choice
        self.set_first_user_choice(random.choice(self.get_available_choices()))
        self.set_host_choice(random.choice(self.get_available_choices()))
        self.set_second_user_choice(self.get_first_user_choice())
    def play_switch_game(self):
        # user always switches door for second choice
        self.set_first_user_choice(random.choice(self.get_available_choices()))
        self.set_host_choice(random.choice(self.get_available_choices()))
        ac = self.get_available_choices()
        ac.remove(self.get_first_user_choice())
        self.set_second_user_choice(ac[0])

print("User always sticks with first choice.")
wins = 0      
for i in range(10000):
    g = MontyHallGame()
    g.play_stick_game()
    if g.get_outcome() == "car":
        wins += 1
print(wins)

print("User randomly decides whether to stick with or switch choice.")
wins = 0      
for i in range(10000):
    g = MontyHallGame()
    g.play_random_game()
    if g.get_outcome() == "car":
        wins += 1
print(wins)

print("User always switches choice.")
wins = 0      
for i in range(10000):
    g = MontyHallGame()
    g.play_switch_game()
    if g.get_outcome() == "car":
        wins += 1
print(wins)

```

Sample output:

```
User always sticks with first choice.
3363
User randomly decides whether to stick with or switch choice.
5001
User always switches choice.
6666

```

The results suggest that the three strategies offer the user the following probabilities of winning the car:

- always stick with the first choice: 1/3
- randomly decide whether to stick or switch: 1/2
- always switch: 2/3

---

<div class="post-metadata">

**Author:** ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)\
**Post date:** [July 30, 2021, 1:37pm UTC](https://discourse.processing.org/t/monty-hall-simulation-problem/31481/4 "2021-07-30T13:37:26Z")

</div>

A bit off topic, but where can I find the details behind the 10 door Monty Hall problem? I think there was a change to the usual 3 doors. Not too sure about the details. I think there was something to do with “You can open 5 more doors, or I can open 5 empty ones” or something along the lines.

Thank you!

---

<div class="post-metadata">

**Author:** ![javagar](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/javagar/32/11434_2.png) [@javagar](https://discourse.processing.org/u/javagar)\
**Post date:** [July 30, 2021, 5:51pm UTC](https://discourse.processing.org/t/monty-hall-simulation-problem/31481/5 "2021-07-30T17:51:32Z")

</div>

Due to the amount of discussion of the problem among mathematicians and others, lots of variants have been developed, so there may be several versions of it that involve ten doors. This article presents something of that sort:

> **[Making the Monty Hall problem weirder but obvious](https://dynomight.net/2020/09/17/making-the-monty-hall-problem-weirder-but-obvious/)**
>
> The Monty Hall problem’s solution is obvious if you start with a weird version of it.

---

<div class="post-metadata">

**Author:** ![javagar](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/javagar/32/11434_2.png) [@javagar](https://discourse.processing.org/u/javagar)\
**Post date:** [July 30, 2021, 11:59pm UTC](https://discourse.processing.org/t/monty-hall-simulation-problem/31481/6 "2021-07-30T23:59:56Z")

</div>

Below is an image of a Monty Hall problem simulation executing in Processing Python Mode.  
 ![MontyHall](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/2X/7/7f2474a27a1b4c7711feaa29ca115e7d6e17d530.png)

It is derived from the Python 3 simulation that was previously posted. During each frame, each of the three player strategies is run 100 times, and the percentages of the wins for that frame are displayed. The percentages are also represented graphically to the right. The graphical representation is cumulative.

All are free to copy, revise, and use the code.

The code:

```auto
import random
iterations = 100

graph_x = 200
def setup():
    size(320, 240)
    frameRate(0.5)
    background(255)
    fill(0)
    stroke(0)
    # labels
    textSize(16)
    text("0%", graph_x - 8, 220)
    text("100%", graph_x + 76, 220)
    line(graph_x, 92, graph_x, 200)
    line(graph_x + 100, 92, graph_x + 100, 200)
    textSize(24)
    text("Monty Hall Problem", 20, 40)
    text("Wins", 20, 80)
    text("Player Strategy", 96, 80)
    text("Stick", 96, 120)
    text("Random", 96, 160)
    text("Switch", 96, 200)

def draw():
    # obscure previous win percentages and frameCount
    noStroke()
    fill(255)
    rect(0, 94, 88, height - 90)
    rect(0, 210, 140, 30)
    
    # display current win percentages
    fill(0)
    textSize(24)
    # stick player strategy
    stick_wins = 0      
    for i in range(iterations):
        g = MontyHallGame()
        g.play_stick_game()
        if g.get_outcome() == "car":
            stick_wins += 1
    text("{}%".format(stick_wins), 20, 120)

    # random player strategy
    random_wins = 0      
    for i in range(iterations):
        g = MontyHallGame()
        g.play_random_game()
        if g.get_outcome() == "car":
            random_wins += 1
    text("{}%".format(random_wins), 20, 160)

    # switch player strategy
    switch_wins = 0      
    for i in range(iterations):
        g = MontyHallGame()
        g.play_switch_game()
        if g.get_outcome() == "car":
            switch_wins += 1
    text("{}%".format(switch_wins), 20, 200)
    textSize(16)
    text("Frame {}".format(frameCount), 10, 230)

    # graph the percentages
    stroke(0, 16)

    line(graph_x + stick_wins, 92, graph_x + stick_wins, 120)
    line(graph_x + random_wins, 132, graph_x + random_wins, 160)
    line(graph_x + switch_wins, 172, graph_x + switch_wins, 200)

class MontyHallGame(object):
    def __init__ (self):
        self.doors = ["goat", "goat", "car"]
        random.shuffle(self.doors)
        self.available_choices = [0, 1, 2]
        self.first_user_choice = None # first door picked by user
        self.host_choice = None # door opened by host
        self.second_user_choice = None # second door picked by user
    def set_first_user_choice(self, door):
        self.first_user_choice = door
        self.available_choices.remove(door)
        for i in self.available_choices:
            if self.doors[i] == "car":
                self.available_choices.remove(i)
                break
    def get_first_user_choice(self):
        return self.first_user_choice
    def set_host_choice(self, door):
        self.host_choice = door
        self.available_choices = [0, 1, 2]
        self.available_choices.remove(door)
    def get_host_choice(self):
        return self.host_choice
    def set_second_user_choice(self, door):
        self.second_user_choice = door
    def get_second_user_choice(self):
        return self.second_user_choice
    def get_outcome(self):
        return self.doors[self.second_user_choice]
    def get_available_choices(self):
        return self.available_choices
    def get_doors(self):
        return self.doors

    # methods for the three user strategies
    # the host always chooses randomly among the two other doors
    # when user's first choice is the door with the car
    
    def play_random_game(self):
        # user randomly chooses from unopened doors for second choice
        self.set_first_user_choice(random.choice(self.get_available_choices()))
        self.set_host_choice(random.choice(self.get_available_choices()))
        self.set_second_user_choice(random.choice(self.get_available_choices()))
    def play_stick_game(self):
        # user always repeats first choice again as second choice
        self.set_first_user_choice(random.choice(self.get_available_choices()))
        self.set_host_choice(random.choice(self.get_available_choices()))
        self.set_second_user_choice(self.get_first_user_choice())
    def play_switch_game(self):
        # user always switches door for second choice
        self.set_first_user_choice(random.choice(self.get_available_choices()))
        self.set_host_choice(random.choice(self.get_available_choices()))
        ac = self.get_available_choices()
        ac.remove(self.get_first_user_choice())
        self.set_second_user_choice(ac[0])

```

---

<div class="post-metadata">

**Author:** ![CodeMasterX](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/codemasterx/32/2942_2.png) [@CodeMasterX](https://discourse.processing.org/u/CodeMasterX)\
**Post date:** [July 31, 2021, 12:13pm UTC](https://discourse.processing.org/t/monty-hall-simulation-problem/31481/7 "2021-07-31T12:13:11Z")

</div>

Here is my take on this with 3 doors (in processing java mode)

> **Code**
>
> ```auto
> long w = 0, t = 0;
> void setup() {
> float swapChance=0.5;
> for (int i = 0; i < 10000000; i++) {
> if (simulate(swapChance)) w++;
> t++;
> }
> println((float)w/(float)t);
> }
> boolean simulate(float swapRate) {
> boolean won;
> 
> boolean correct[] = new boolean[3];
> int cr =(int)random(3);
> correct[cr] = true;
> int pick=(int)random(3);
> boolean swap = (random(1)>swapRate);
> if (swap) { 
> if(pick!=cr) pick = cr;
> else pick = ((correct[0]==false)? 0 : ((correct[1]==false)? 1 : 2));
> }
> won = correct[pick];
> return won;
> }
> 
> ```

I have skipped the host opening the empty door since it is always empty (host knows the empty doors).  
Therefore, I just ask if he wants to swap. If he originally had the correct door, he will loose, otherwise he wins.

---

<div class="post-metadata">

**Author:** ![monkstone](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/monkstone/32/64_2.png) [@monkstone](https://discourse.processing.org/u/monkstone)\
**Post date:** [July 31, 2021, 12:43pm UTC](https://discourse.processing.org/t/monty-hall-simulation-problem/31481/8 "2021-07-31T12:43:29Z")

</div>

Just in case anyone is unfamiliar with problem view [this clip from BBC.](https://www.bbc.co.uk/news/av/magazine-24047377)

---

<div class="post-metadata">

**Author:** ![javagar](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/javagar/32/11434_2.png) [@javagar](https://discourse.processing.org/u/javagar)\
**Post date:** [July 31, 2021, 4:54pm UTC](https://discourse.processing.org/t/monty-hall-simulation-problem/31481/9 "2021-07-31T16:54:51Z")

</div>

Thanks for the simulation, @CodeMasterX, and the video, @monkstone.

From the video and the other media we have seen, it is evident that there is much confusion out there regarding this problem.

Perhaps the following could clarify it.

We start out with the following, in any order:

| door 1 | door 2 | door 3 |
| goat | goat | car |

If the contestant chooses a door and sticks with it, regardless of what the host does, there is a 1/3 chance of winning the car.

Of course, the initial configuration could be any of the following:

| door 1 | door 2 | door 3 |
| goat | goat | car |

  

| door 1 | door 2 | door 3 |
| goat | car | goat |

  

| door 1 | door 2 | door 3 |
| car | goat | goat |

Let’s assume the contestant begins by choosing door 1, and has decided to switch, regardless of what the host does. That leaves one of the following, with a 1/3 probability for each one:

| door 2 | door 3 |
| goat | car |

  

| door 2 | door 3 |
| car | goat |

  

| door 2 | door 3 |
| goat | goat |

Now the host opens one of the doors, either 2 or 3, revealing a goat. The door is chosen at random from the one or both that remain that have a goat.

Then, what remains is one of the following, with 1/3 probability of each:

| remaining door |
| car |

  

| remaining door |
| car |

  

| remaining door |
| goat |

The contestant, having decided in advance to switch, picks whichever door remains, with a 1/3 probability for each configuration above. Since two of those configurations contain the car, there is a 2/3 probability of winning it. The configurations and their probabilities would be equivalent, regardless of which door the contestant had chosen in the first place.

Therefore, switching is the best strategy.
