class Factory attr_reader :bots, :bins def initialize @bots = Hash.new {|h,k| h[k] = Bot.new(self) } @bins = Hash.new {|h,k| h[k] = Bin.new } end def <<(instruction) case instruction when /value (\d+) goes to bot (\d+)/ bots[$2.to_i] << $1.to_i when /bot (\d+) gives low to (.+) (\d+) and high to (.+) (\d+)/ bot = bots[$1.to_i] bot.outs = [out($2, $3.to_i), out($4, $5.to_i)] else raise "invalid instruction: #{instruction}" end end private def out(type, id) case type when 'bot' bots[id] when 'output' bins[id] else raise "invalid type: #{type}" end end end class Bot attr_reader :factory, :values, :outs, :log def initialize(factory) @factory = factory @values = [] @log = [] end def <<(value) values << value try_run end def outs=(outs) @outs = outs try_run end private def try_run return unless outs && values.size == 2 log << values.sort low, high = values.sort values.clear outs[0] << low outs[1] << high end end class Bin attr_reader :value def <<(value) @value = value end end if __FILE__ == $0 factory = Factory.new DATA.each_line do |line| factory << line end p factory.bins.values_at(0, 1, 2).map(&:value).inject(:*) end require 'minitest' # require 'minitest/autorun' class TestDay10 < Minitest::Test def test_day_10 instructions = <