Created
February 27, 2012 20:35
-
-
Save alexaandru/1926859 to your computer and use it in GitHub Desktop.
Monty Hall model in Ruby
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 | |
# We randomly sort the remaining doors so that | |
# Monty doesn't get to always pick the first | |
# door (or the last). | |
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, @remaining_door = d1, d2 | |
else | |
@monty_pick, @remaining_door = d2, 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 = @doors_content[@guest_pick].eql?(:prize) | |
if @show_backstage | |
puts <<BACKSTAGE | |
----------------------------------------------------------------------------------------- | |
Prizes were : door #1 #{@doors_content[0]}, door #2 #{@doors_content[1]}, door #3 #{@doors_content[2]} | |
Guest picked : door ##{@guest_pick + 1} (#{@doors_content[@guest_pick]}) | |
Monty picked : door ##{@monty_pick + 1} (#{@doors_content[@monty_pick]}) | |
Remaining : door ##{@remaining_door + 1} (#{@doors_content[@remaining_door]}) | |
The quest #{@do_switch ? 'did' : 'did not'} switch the door. | |
----------------------------------------------------------------------------------------- | |
BACKSTAGE | |
end | |
@result | |
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, failure = 0, 0 | |
# This runs all the shows we asked for | |
no_of_shows.times { MontyHall.new(do_switch, show_backstage).result ? success += 1 : failure += 1 } | |
# And finally, we compute & display the rate | |
puts "Success rate when we %s switch is: %.2f%" % [do_switch ? "do" : "don't", ((success * 100.0)/no_of_shows)] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment