Last active
September 22, 2019 18:38
-
-
Save Michael-J-Ward/e7e939213ea8448124ac85220163cd54 to your computer and use it in GitHub Desktop.
Monte Carlo'ing a modified monty python variant
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Monte Carlo'ing Hillogram's Monty Hall Variant | |
Hillelogram on twitter came up with a surprising Monty Hall Variant: https://twitter.com/hillelogram/status/1175125663247998978 | |
[BEGIN EDIT] | |
@hillelogram gives credit to this paper https://pubs.aeaweb.org/doi/pdfplus/10.1257/jep.33.3.144 | |
/u/edderiofer on reddit pointed out that this is in fact the "Monty Crawl" variant from here: http://www.probability.ca/jeff/writing/montyfall.pdf | |
[END EDIT] | |
This source code is modified from its original version here: https://blog.teamtreehouse.com/modeling-monty-hall-problem-python | |
""" | |
from collections import namedtuple | |
import random | |
# Create an easy-to-return and easy-to-inspect data | |
# structure for Game results. | |
Results = namedtuple('Results', ['won', 'initial_door', 'monty_door']) | |
class Door: | |
def __init__(self, location): | |
self.location = location | |
self.prize = False | |
self.opened = False | |
class Game: | |
"""Monty Hall, always switch""" | |
def __init__(self, monty_selection_func): | |
self.monty_selection_func = monty_selection_func | |
self.chosen_door = None | |
self.initial_door = None | |
self.monty_door = None | |
self.doors = [ | |
Door(i) for i in range(1, 4) | |
] | |
# Pick a random door and give it a prize | |
random.choice(self.doors).prize = True | |
def pick_door(self): | |
self.initial_door = random.choice(self.doors) | |
def open_false_door(self): | |
# Get the non-chosen doors | |
available_doors = [door for door in self.doors | |
if door is not self.initial_door | |
and not door.prize] | |
self.monty_door = self.monty_selection_func(available_doors) | |
self.monty_door.opened = True | |
def switch_doors(self): | |
# Always Switch | |
available_door = [door for door in self.doors | |
if door is not self.initial_door | |
and not door.opened][0] | |
self.chosen_door = available_door | |
@classmethod | |
def play(cls, monty_selection_func): | |
game = cls(monty_selection_func) | |
game.pick_door() | |
game.open_false_door() | |
game.switch_doors() | |
won = game.chosen_door.prize | |
initial_door = game.initial_door.location | |
monty_door = game.monty_door.location | |
return Results(won, initial_door, monty_door) | |
def monty_chooses_lowest(doors): | |
return doors[0] | |
def monty_chooses_random(doors): | |
return random.choice(doors) | |
# Play play 1e6 runs of the game to get significant numbers | |
num_simulations = int(1e6) | |
games = [Game.play(monty_chooses_lowest) for _ in range(num_simulations)] | |
# Find Games where we select 2 and monty selects 1 | |
scenario_games = [game for game in games if game.initial_door == 2 and game.monty_door == 1] | |
wins = sum(x.won for x in scenario_games) | |
num_scenario_games = len(scenario_games) | |
win_percentage = 100 * wins / num_scenario_games | |
print("Won {:.2f}% when monty chose the lowest non-prize door: {:,} out of {:,}".format(win_percentage, wins, num_scenario_games)) | |
# Play play 1e6 runs of the game to get significant numbers | |
num_simulations = int(1e6) | |
games = [Game.play(monty_chooses_random) for _ in range(num_simulations)] | |
# Find Games where we select 2 and monty selects 1 | |
scenario_games = [game for game in games if game.initial_door == 2 and game.monty_door == 1] | |
wins = sum(x.won for x in scenario_games) | |
num_scenario_games = len(scenario_games) | |
win_percentage = 100 * wins / num_scenario_games | |
print("Won {:.2f}% when monty chooses random non-prize door: {:,} out of {:,}".format(win_percentage, wins, num_scenario_games)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment