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.