Adam Karolczak
Adam Karolczak

Reputation: 235

Monty Hall simulator has a wrong outcome

I wanted to do something seemingly simple and at the same time prove Monty Hall by code, and sadly what I got was not a proof of the problem, but the complete opposite. No matter if I switch or not, I get ~33% odds of winning across 10000 simulations. Could you check the code and see what's wrong with it? Keep in mind that I'm a web-dev so my Python skills are not great and the code might not look fantastic (for example, I made a removable_doors list where just a variable would've worked fine). Cheers!

import random
av_doors = [1, 2, 3]
door_v = [1, 2, 3]
removable_doors = [1, 2, 3]
score = 0
loses = 0

door = int(input("Choose your door (1-3)"))
pick = int(door)-1

dec = input("Stay or switch? (0/1)")

n = 0
while n < 10000:
    removable_doors = [1, 2, 3]
    av_doors = [1, 2, 3]
    val = random.randint(1,3)
    if val == 1:
        door_v[0] = 1
        door_v[1] = 0
        door_v[2] = 0
        removable_doors.remove(1)
    elif val == 2:
        door_v[0] = 0
        door_v[1] = 1
        door_v[2] = 0
        removable_doors.remove(2)
    elif val == 3:
        door_v[0] = 0
        door_v[1] = 0
        door_v[2] = 1
        removable_doors.remove(3)

    try:
        removable_doors.remove(int(door))
    except:
        pass

    av_doors.remove(door)

    if len(removable_doors) == 2:
        rand_door = random.randint(0,1)
        if rand_door == 0:
            del av_doors[0]
        elif rand_door ==1:
            del av_doors[1]
    else:
        del av_doors[0]

    if dec == "1":   
        door = av_doors[0]
    else:
        pass

    pick = door-1
    if door_v[pick] == 1:
        score+=1
    else:
        loses+=1

    n+=1

print(score)
print(loses)

Upvotes: 2

Views: 149

Answers (1)

gdelab
gdelab

Reputation: 6220

Your host sometimes removes a door with the car behind it... Here is a solution that works, and (I think) a bit better written, while keeping your structures (in python3 but that should not raise troubles):

import random

win = 0
lose = 0

switch = int(input("Stay or switch? (0-stay/1-switch):")) == 1

n = 0
while n < 10000:
    # Init
    door_values = [0, 0, 0]
    removable_doors = [0, 1, 2]
    available_doors = [0, 1, 2]

    # Placing the reward somewhere
    car_place = random.randint(0, 2)
    door_values[car_place] = 1
    removable_doors.remove(car_place)

    # Choose a door
    door_chosen = random.randint(0, 2)
    available_doors.remove(door_chosen)
    if door_chosen != car_place:
        removable_doors.remove(door_chosen)

    # Host removes a door that does not have the car and has not been chosen by the player

    door_removed_by_host = removable_doors[random.randint(0, len(removable_doors)-1)]
    available_doors.remove(door_removed_by_host)

    # Switch if specified
    if switch:
        assert(len(available_doors) == 1)
        door_chosen = available_doors[0]

    # Check the result
    if car_place == door_chosen:
        win += 1
    else:
        lose += 1

    n+=1

print('win=%s'%str(win))
print('lose=%s'%str(lose))
print('ratio=%s'%str(win/(win+lose)))

It gives me 0.3332 when switch=False, 0.6738 for switch=True, I guess this rather confirms Monty Hall's solution :)

Upvotes: 2

Related Questions