Last active
July 14, 2016 04:19
-
-
Save dangerous/28a4a031778cafa6be1b8100626abd2b to your computer and use it in GitHub Desktop.
Monty Hall problem where host picks randomly - based on https://gist.github.com/alexaandru/1926859
This file contains 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
# | |
# This class creates a model of the Monty Hall problem. | |
# It simulates arranging the set with prize/goats, both guest | |
# and Monty picking a door and then the decision to switch | |
# or not to switch (and of course, the outcome). | |
# | |
# Each instance of the class (MontyHall.new) runs a new | |
# show. Sample usage code is at the bottom. | |
# | |
class MontyHall | |
attr_accessor :doors, :result | |
# | |
# We start with three doors, randomly sorted. | |
# Then we run through the entire scenario as | |
# outlined below. | |
# | |
def initialize(do_switch = true, show_backstage = false) | |
@doors = [0, 1, 2].sort_by { rand } | |
@doors_content = Array.new(3) | |
@do_switch = do_switch | |
@show_backstage = show_backstage | |
set_the_stage | |
guest_pick | |
monty_pick | |
guest_decide_to_switch_or_not | |
determine_outcome | |
end | |
# | |
# Set the stage: put a prize behind one door, | |
# a goat behind the two remaining doors. | |
# | |
def set_the_stage | |
# put a prize at a random door | |
@doors_content[rand(3)] = :prize | |
# put a goat on all other doors | |
3.times { |i| @doors_content[i] ||= :goat } | |
end | |
# | |
# Guest takes his pick. | |
# | |
def guest_pick | |
# The doors are already randomly sorted, so we just | |
# pop out a door from the top of the stack. | |
@guest_pick = @doors.pop | |
end | |
# | |
# Monty takes his pick, always picking a :goat | |
# door. | |
# | |
def monty_pick | |
# always pick d1 | |
# comment these three lines to use original MH problem | |
@monty_pick = @doors.first | |
@remaining_door = @doors.last | |
return | |
d1, d2 = @doors.sort_by { rand } | |
# And we also make sure that we have a goat | |
# behind the door Monty opens. | |
if @doors_content[d1].eql?(:goat) | |
@monty_pick = d1 | |
@remaining_door = d2 | |
else | |
@monty_pick = d2 | |
@remaining_door = d1 | |
end | |
end | |
def guest_decide_to_switch_or_not(_do_switch = @do_switch) | |
@guest_pick, @remaining_door = @remaining_door, @guest_pick if @do_switch | |
end | |
def determine_outcome | |
@result = if @doors_content[@monty_pick].eql? :prize | |
nil | |
elsif @doors_content[@guest_pick].eql?(:prize) | |
true | |
else | |
false | |
end | |
end | |
end | |
# This controls the number of shows we play | |
no_of_shows = 100_000 | |
# This controls the switching decision, can be set to: true or false | |
# It will be used for ALL shows we run at once. | |
do_switch = false | |
# Show backstage tips. Don't set it unless you run really small loops. | |
show_backstage = false | |
# This counts the success/failure of all shows we played | |
success = 0 | |
failure = 0 | |
# This runs all the shows we asked for | |
no_of_shows.times do | |
result = MontyHall.new(do_switch, show_backstage).result | |
success += 1 if result === true | |
failure += 1 if result === false | |
end | |
# And finally, we compute & display the rate | |
puts 'Success rate when we %s switch is: %.2f%' % [do_switch ? 'do' : "don't", ((success * 100.0) / (success + failure))] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment