Skip to content

Instantly share code, notes, and snippets.

@chadgh
Created March 31, 2017 15:18
Show Gist options
  • Save chadgh/c91b50d73cbedfc721fa9bd587b84788 to your computer and use it in GitHub Desktop.
Save chadgh/c91b50d73cbedfc721fa9bd587b84788 to your computer and use it in GitHub Desktop.
Simulation of the Monty Hall / Game show problem
from abc import ABCMeta, abstractmethod
from random import choice
def game(player):
# determine winning and loosing doors for this round
doors = [1, 2, 3]
winning_door = choice(doors)
loosing_doors = [d for d in doors if d != winning_door]
# let player pick a door
player_choice = player.pick(doors)
# remove a door
doors = [d for d in doors if d == winning_door or d == player_choice]
if len(doors) != 2:
doors.append(choice(loosing_doors))
# allow player to switch choice
player_choice = player.switch(doors)
# determine if the player won
if player_choice == winning_door:
return 'win'
else:
return 'lose'
class Player(metaclass=ABCMeta):
@abstractmethod
def pick(self, doors):
...
@abstractmethod
def switch(self, doors):
...
class RandomPlayer(Player):
def pick(self, doors):
return choice(doors)
def switch(self, doors):
return choice(doors)
class AlwaysKeepPlayer(Player):
def pick(self, doors):
self.my_choice = choice(doors)
return self.my_choice
def switch(self, doors):
return self.my_choice
class AlwaysSwitchPlayer(Player):
def pick(self, doors):
self.my_choice = choice(doors)
return self.my_choice
def switch(self, doors):
return [d for d in doors if d != self.my_choice][0]
def simulate(player_class, rounds=1000):
wins = 0
for _ in range(rounds):
result = game(player_class())
wins += 1 if result == 'win' else 0
percent_wins = (wins / rounds) * 100
print('{} won {:.1f}% of the time.'.format(
player_class.__name__,
percent_wins,
))
if __name__ == '__main__':
simulate(RandomPlayer, rounds=10000)
simulate(AlwaysKeepPlayer, rounds=10000)
simulate(AlwaysSwitchPlayer, rounds=10000)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment