class BotFactory attr_reader :bots attr_reader :outputs def initialize @bots = {} @outputs = {} end def add_bot(bot) bots[bot.number] = bot end def bot_exists?(bot_number) bots.key? bot_number end def give_chip(bot_number, chip_number) bot = bots[bot_number] bot = Bot.new self, bot_number if bot.nil? bot.give_chip chip_number end def take_chips(bot_number) bots[bot_number].take_chips end def output_chip(output_number, chip_number) outputs[output_number] = [] if outputs[output_number].nil? outputs[output_number].push chip_number end def to_s "#{bots.values.map(&:to_s).join("\n")}\n\n#{outputs}" end end class Bot attr_reader :number, :microchips def initialize(factory, number) @factory = factory @number = number @microchips = [] factory.add_bot self end def give_chip(chip_number) microchips.push chip_number end def take_chips chips = microchips.sort.clone @microchips = [] chips end def to_s "Bot #{number} has #{microchips}" end end class Command def self.for(string) (string[0] == "b" ? GiveCommand : InitCommand).for string end end class GiveCommand < Command attr_reader :source, :low_type, :low_number, :high_type, :high_number def self.for(string) new *string.match(/bot (\d*) gives low to (\w*) (\d*) and high to (\w*) (\d*)/).captures end def initialize(source, low_type, low_number, high_type, high_number) @source = source.to_i @low_type = low_type @low_number = low_number.to_i @high_type = high_type @high_number = high_number.to_i end def init_command? false end def execute(bot_factory) low, high = bot_factory.take_chips(source) give(bot_factory, low_type, low_number, low) give(bot_factory, high_type, high_number, high) end def give(bot_factory, type, number, to_give) if type == "bot" bot_factory.give_chip number, to_give else bot_factory.output_chip number, to_give end end end class InitCommand < Command def self.for(string) new *string.match(/value (\d*) goes to (\w*) (\d*)/).captures end attr_reader :chip_number, :to_type, :to_number def initialize(chip_number, to_type, to_number) @chip_number = chip_number.to_i @to_type = to_type @to_number = to_number.to_i end def init_command? true end def execute(bot_factory) bot_factory.give_chip to_number, chip_number end end input = STDIN.read.chomp command_strings = input.split "\n" commands = command_strings.map { |string| Command.for string } init_commands, non_init_commands = commands.partition(&:init_command?) bot_factory = BotFactory.new init_commands.each { |command| command.execute bot_factory } non_init_commands.each { |command| command.execute bot_factory } puts bot_factory.to_s