aoc_omni/ruby/2016/10/problem.rb
2025-11-30 21:22:21 -05:00

137 lines
2.8 KiB
Ruby

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