Skip to content

Instantly share code, notes, and snippets.

@ccoenen
Last active August 29, 2015 14:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ccoenen/50931659c9cf554b9058 to your computer and use it in GitHub Desktop.
Save ccoenen/50931659c9cf554b9058 to your computer and use it in GitHub Desktop.
Monty Hall Problem Simulator

The Monty Hall Problem is a probability puzzle.

When i read this article about Marilyn vos Savant, my initial reaction was "that can't be right". I continued to read the comments, the wikipedia page and then started a table to see if this was indeed the case. Being a programmer, i then started a simulation.

This is what it turned out to be.

The concise explanation is: The door's chance does not change. This became apparent right when i started coding. Maybe it helps anyone else understanding the problem, and also the general brainfuck that is probability.

# This code is Licensed under CC-0 / Public Domain / WTFPL
# Written by Claudius Coenen <opensource@amenthes.de>
# Related reading:
# - http://priceonomics.com/the-time-everyone-corrected-the-worlds-smartest/
# - http://en.wikipedia.org/wiki/Monty_Hall_problem
class MontyHall
def initialize(doors, eliminations)
@available_doors = (0...doors).to_a
@prize_door = @available_doors[rand(doors)]
@eliminations = eliminations
end
def run
@initial_choice = choose_random
puts "Prize at #{@prize_door}, You're selecting #{@initial_choice}." if VERBOSITY > 1
print_choices if VERBOSITY > 3
host_eliminates = eliminate_doors_except([@initial_choice])
puts " Host eliminates #{host_eliminates.join(', ')}." if VERBOSITY > 2
print_choices if VERBOSITY > 3
@available_doors.delete @initial_choice
@altered_choice = choose_random
puts " Choice changed to #{@altered_choice}." if VERBOSITY > 2 && @altered_choice != @initial_choice
end
def choose_random
@available_doors[rand(@available_doors.length)]
end
def eliminate_doors_except(exceptions)
elimination_candidates = @available_doors - exceptions - [@prize_door]
host_eliminates = []
@eliminations.times do
eliminate = elimination_candidates.delete_at rand(elimination_candidates.length)
host_eliminates.push eliminate
end
@available_doors -= host_eliminates
host_eliminates
end
def print_choices
puts " Your current choices are #{@available_doors.join(', ')}."
end
def initial_choice_correct?
@initial_choice == @prize_door
end
def altered_choice_correct?
@altered_choice == @prize_door
end
end
VERBOSITY = 1
iterations = 10000
(3..5).to_a.each do |doors|
(0..3).to_a.each do |eliminations|
# you can't run this test unless you have anything to switch to. (doors must be at least eliminations + 2)
next if eliminations > doors - 2
puts "Monty Hall with #{iterations} iterations of #{doors} doors and #{eliminations} eliminations" if VERBOSITY > 0
win_by_keeping = 0
win_by_switching = 0
iterations.times do
mh = MontyHall.new(doors, eliminations)
mh.run
win_by_keeping += 1 if mh.initial_choice_correct?
win_by_switching += 1 if mh.altered_choice_correct?
end
puts " Keeping wins #{win_by_keeping}/#{iterations} times" if VERBOSITY > 0
puts " Switching wins #{win_by_switching}/#{iterations} times" if VERBOSITY > 0
end
end
Slightly formatted sample output for 10000 iterations
Monty Hall with 10000 iterations of 3 doors and 0 eliminations
Keeping wins 3297/10000 times
Switching wins 3392/10000 times
Monty Hall with 10000 iterations of 3 doors and 1 eliminations
Keeping wins 3308/10000 times
Switching wins 6692/10000 times
Monty Hall with 10000 iterations of 4 doors and 0 eliminations
Keeping wins 2516/10000 times
Switching wins 2536/10000 times
Monty Hall with 10000 iterations of 4 doors and 1 eliminations
Keeping wins 2510/10000 times
Switching wins 3740/10000 times
Monty Hall with 10000 iterations of 4 doors and 2 eliminations
Keeping wins 2527/10000 times
Switching wins 7473/10000 times
Monty Hall with 10000 iterations of 5 doors and 0 eliminations
Keeping wins 2020/10000 times
Switching wins 1986/10000 times
Monty Hall with 10000 iterations of 5 doors and 1 eliminations
Keeping wins 1945/10000 times
Switching wins 2715/10000 times
Monty Hall with 10000 iterations of 5 doors and 2 eliminations
Keeping wins 1984/10000 times
Switching wins 3957/10000 times
Monty Hall with 10000 iterations of 5 doors and 3 eliminations
Keeping wins 2076/10000 times
Switching wins 7924/10000 times
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment