All pastes #63389 Raw Edit

Anonymous

public text v1 · immutable
#63389 ·published 2006-06-09 18:40 UTC
rendered paste body
$verbosity = 0
@tests = []

def report(msg)
  puts msg if $verbosity == 2
end

def setup!(bf)
  @highest_floor = 99
  @break_floor = bf
  @eggs_in_hands = 2
  @eggs_on_ground = 0
  @floor, @walks, @drops = 0,0,0
  @solution = false
end

def walk(arg)
  if arg.is_a? Symbol
    walk arg => 1
  elsif arg[:to]
    if arg[:to] < 0 || arg[:to] > @highest_floor
      puts "Cannot go to floor #{arg[:to]}"
      return false
    end
    @walks += (@floor - arg[:to]).abs
    @floor = arg[:to]
    report "Walk to #{@floor}"
    true
  elsif arg[:up]
    walk :to => (@floor + arg[:up])
  elsif arg[:down]
    walk :to => (@floor - arg[:down])
  end
end

def drop_egg!
  @egg_broken = false
  @drops += 1
  if @eggs_in_hands <= 0
    puts "No eggs to drop"
    return
  end
  @eggs_in_hands -= 1
  if @break_floor > floor
    @eggs_on_ground += 1
    report "Dropped egg! -- Didn't break"
  else
    @egg_broken = true
    report "Dropped egg! -- Whoa, broken!"
  end
end

def egg_broken?
  @egg_broken
end

def eggs_in_hands?
  eggs_in_hands > 0
end

def no_eggs_in_hands?
  !eggs_in_hands?
end

def eggs_in_hands
  @eggs_in_hands
end

def eggs
  @eggs_in_hands + @eggs_on_ground
end

def pick_up_eggs!
  report "Picking up eggs -- found #{@eggs_on_ground}"
  verb = $verbose
  $verbose = false
  walk :to => 0
  $verbose = verb
  @eggs_in_hands += @eggs_on_ground
  @eggs_on_ground = 0
end

def floor
  @floor
end

def highest_floor
  @highest_floor
end

def report_solution!(floor)
  @solution = floor
  throw :finished
end

def test(algorithm, &alg_proc)
  @tests << [algorithm, alg_proc]
end

def run_test(break_floor, alg)
  setup!(break_floor)
  catch :finished do
    alg[1].call
  end
  
  {:algorithm => alg[0], :walks => @walks, :drops => @drops, :solved => @solution == @break_floor, :solution => @solution}
end

def run_tests!
  results = []
  
  for alg in @tests
    for n in (1..99)
      results << run_test(n, alg)
    end
  end
  
  if $verbosity == 1 || $verbosity == 2
    for result in results
      puts "\"#{result[:algorithm]}\" #{result[:solved] ? 'solved' : 'didn\'t solve'} the puzzle. It took #{result[:walks]} walks and #{result[:drops]} drops. Solution: #{result[:solution]}"
    end
  end
  
  for alg in @tests
    alg_results = results.select{|r| r[:algorithm] == alg[0]}
    
    walks = alg_results.inject(0){|n,r| r[:walks] + n}
    drops = alg_results.inject(0){|n,r| r[:drops] + n}
    solutions = alg_results.inject(0){|n,r| r[:solved] ? n + 1 : n}
      
    puts "\"#{alg[0]}\" solved #{solutions} of #{results.size / @tests.size} puzzles. It took #{walks} walks and #{drops} drops"
  end
end

test "Simple algorithm" do
  next_floor = 0
  while eggs_in_hands?    
    walk :to => next_floor
    next_floor = floor + 1
    drop_egg!
    if egg_broken?
      report_solution! floor
    elsif no_eggs_in_hands?
      pick_up_eggs!
    end
  end
end

test "Skip 7 algorithm" do
  n = 6
  next_floor = n + 1
  while eggs != 0
    if no_eggs_in_hands?
      pick_up_eggs!
    elsif eggs == 1
      walk :to => next_floor
      next_floor = floor + 1 if floor != 99
      drop_egg!
      if egg_broken?
        report_solution! floor
      end
    else
      walk :to => next_floor
      drop_egg!
      if egg_broken?
        next_floor = floor - n
      else
        if floor + n + 1 > 99
          next_floor = floor + 1
        else
          next_floor = floor + n + 1
        end
      end
    end
  end
end