137 lines
2.8 KiB
Ruby
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
|