Monty Hall Python

Monty Hall problem simulation.
Player picks one of three doors (to win a car). Without opening the players door, the host opens a non-winning door (or win a goat). The player then can switch to the other closed door and stay with the first choice.

import random

def main(trials=12345, number_doors=3):
    # SHOW THE RANDOMNESS OF THE GAME SETUP
    show_game_randomness(trials, number_doors)
    
    # TEST NEVER SWITCHING AND ALWAYS SWITCHING
    # TRY NEVER SWITCHING
    trues = 0
    for trial in xrange(trials):
        is_car = play_a_game(SWITCH=False, number_doors=number_doors)
        if is_car: trues += 1
    print '{0} games and never switching: {1} wins ({2:.2%})'.format(
           trials, trues, trues/float(trials))
    # TRY ALWAYS SWITCHING
    trues = 0
    for trial in xrange(trials):
        is_car = play_a_game(SWITCH=True, number_doors=number_doors)
        if is_car: trues += 1
    print '{0} games and always switching: {1} wins ({2:.2%})'.format(
           trials, trues, trues/float(trials))
    
    
def play_a_game(SWITCH=False, number_doors=3):
    doors = newgame(number_doors)
    whose_door = ['']*number_doors
    # PLAYER SELECTS A DOOR
    whose_door[random.randint(0,number_doors-1)] = 'player'
    
    # HOST SHOWS A GOAT (SELECTS A GOAT DOOR)
    while True:
        host_sel = random.randint(0,number_doors-1)
        if doors[host_sel] != 'car' and whose_door[host_sel] != 'player':
            whose_door[host_sel] = 'host'
            break
        
    # SWITCH DOORS?
    if SWITCH:
        while True:
            player_sel = random.randint(0,number_doors-1)
            if whose_door[player_sel] != 'host' and whose_door[player_sel] != 'player':
                break
        whose_door[whose_door.index('player')] = 'nevermind'
        whose_door[player_sel] = 'player'
        
    # RETURN RESULT
    return True if doors[whose_door.index('player')] == 'car' else False
        
     
def newgame(number_doors=3):
    car_index = random.randint(0,number_doors-1)
    doors = ['goat']*number_doors
    doors[car_index] = 'car'
    return doors
    
    
def show_game_randomness(trials, number_doors=3):
    trial_results = [0]*number_doors    
    while True:
        doors = newgame(number_doors)
        trial_results[doors.index('car')] += 1
        
        if sum(trial_results) >= trials:
            print 'Car occurance:',
            print trial_results, 'times.',
            print ['{0:.2%}'.format(x/float(sum(trial_results))) for x in trial_results]
            break


if __name__ == '__main__':
    main()

When I read this problem and how switching doors is the best solution, it was a little hard to believe. I realized why switching is a good idea when programming the host’s selection process to show a goat. Since 2/3rds of the time, the host is constrained in his choice of the two remaining doors, therefor, 2/3rds of the time, the car is behind the door the host does not pick.

Leave a comment