require 'socket'













class Workshop
  
  def initialize
    @sockets = {}
  end

  
  
  
  
  
  
  
  
  
  def add
    child, parent = UNIXSocket.pair

    wid = fork do
      
      child.close
      @sockets.each_value { |sibling| sibling.close }

      
      
      Signal.trap() { exit! }

      loop do
        
        begin
          command, args = Marshal.load(parent)
        rescue EOFError
          
          break
        end

        case command
        when :work
          
          result = yield *args
          Marshal.dump(result, parent)
        when :remove
          break
        else
          fail 
        end
      end
    end

    
    parent.close
    @sockets[wid] = child
    wid
  end

  
  
  
  
  
  
  
  
  
  
  def work(*args)
    message = [:work, args]
    @sockets.each_pair do |wid, child|
      Marshal.dump(message, child)
    end

    
    result = {}
    @sockets.each_pair do |wid, child|
      begin
        
        result[wid] = Marshal.load(child)
      rescue EOFError
        fail 
      end
    end
    result
  end

  
  
  
  
  def remove(wid)
    unless child = @sockets.delete(wid)
      raise ArgumentError, 
    else
      Marshal.dump([:remove, nil], child)
      child.close
      Process.wait(wid)
    end
  end
end




require 'pp'
shop = Workshop.new
wids = []


@fixed_rand = false
def fix_rand
  unless @fixed_rand; srand; @fixed_rand = true; end
end


6.times do
  wids << shop.add do |i|
    
    fix_rand
    f = proc { |n| if n < 2 then n else f[n - 1] + f[n - 2] end }
    [i, f[25 + rand(10)]]
  end
end

6.times do |i|
  
  pp shop.work(i)

  
  victim = rand(wids.length)
  shop.remove wids[victim]
  wids.slice! victim

  
  wids << shop.add do |j|
    
    
    fix_rand
    f = proc { |n| if n < 3 then n else f[n - 1] + f[n - 2] + f[n - 3] end }
    [j, i, f[20 + rand(10)]]
  end
end


wids.each { |wid| shop.remove wid }
pp shop.work(6)