Skip to content

Instantly share code, notes, and snippets.

@asross
Created January 25, 2014 23:30
Show Gist options
  • Save asross/8625483 to your computer and use it in GitHub Desktop.
Save asross/8625483 to your computer and use it in GitHub Desktop.
A simulation of two solutions to the "prisoner and two switches" problem (http://www.braingle.com/brainteasers/18012/prisoners-and-2-switches-scenario-a.html)
class Leader
attr_reader :count
attr_reader :actually_visited
def initialize
@count = 1
@actually_visited = false
end
def respond_to_state(s)
@actually_visited = true
case s
when '00' then '01'
when '01' then '00'
when '10' then @count += 1 and '00'
when '11' then @count += 1 and '01'
end
end
def respond_to_state_emma(s)
@actually_visited = true
case s
when '00' then '01'
when '01' then '00'
when '10' then @count += 1 and '00'
when '11' then @count += 2 and '01'
end
end
end
class Prisoner
attr_reader :actually_visited
def initialize
@visited = 0
@actually_visited = false
end
def respond_to_state(s)
@actually_visited = true
if @visited == 0
case s
when '00' then @visited = 1 and '10'
when '01' then @visited = 1 and '11'
when '10' then '11'
when '11' then '10'
end
else
case s
when '00' then '01'
when '01' then '00'
when '10' then '11'
when '11' then '10'
end
end
end
def respond_to_state_emma(s)
@actually_visited = true
if @visited < 1
case s
when '00' then @visited += 1 and '10'
when '01' then '00'
when '10' then @visited += 1 and '11'
when '11' then @visited -= 1 and '10'
end
else
case s
when '00' then '01'
when '01' then '00'
when '10' then @visited -= 1 and '00'
when '11' then @visited -= 1 and '10'
end
end
end
end
def run_problem(n, emma=false)
# initialize everything
leader = Leader.new
prisoners = [leader]
(n-1).times do
prisoners << Prisoner.new
end
steps = 0
state = '00'
# run the algorithm
until leader.count >= n
steps += 1
prisoner = prisoners.sample
if emma
state = prisoner.respond_to_state_emma(state)
else
state = prisoner.respond_to_state(state)
end
end
# make sure we didn't fail
if prisoners.any? {|p| !p.actually_visited }
raise "BAD!"
end
# return number of steps
steps
end
n_prisoners = 100
iterations = 100
norm_results = iterations.times.map { run_problem(n_prisoners, false) }
emma_results = iterations.times.map { run_problem(n_prisoners, true) }
puts "For n = #{n_prisoners} prisoners:"
puts "Emma's Average: #{emma_results.inject(0.0){ |sum, el| sum + el }.to_f / iterations}"
puts "Regular Average: #{norm_results.inject(0.0){ |sum, el| sum + el }.to_f / iterations}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment