On Day 10 we are dealing with bots and chips. Each chip has a number or integer value. We also have information which values goes to which bot and what bot should do with those chips. Our input looks like this:
value 5 goes to bot 2
bot 2 gives low to bot 1 and high to bot 0
value 3 goes to bot 1
bot 1 gives low to output 1 and high to bot 0
bot 0 gives low to output 2 and high to output 0
value 2 goes to bot 2
So value 5 and value 2 goes to bot 2. Then bot 2 give low value (2 in this case) to bot 1 and gives high value (5 in this case) to bot 0. And so on and so on. The bot can proceed only when it gets 2 chips.
For first part we need to say what is number of bot comparing chips 61 and 17. Below is my solution:
data = File.readlines("10.txt", chomp: true)
@bots = []
@indexes = {
0 => [],
1 => [],
2 => []
}
@moves = {}
@outputs = []
@target_low_chip = 17
@target_high_chip = 61
def give_to_bot(source_id, target_id, chip)
if source_id
had_chips = @bots[source_id].size
@bots[source_id].delete(chip)
@indexes[had_chips].delete(source_id)
@indexes[had_chips - 1].push(source_id)
end
@bots[target_id] ||= []
had_chips = @bots[target_id].size
@bots[target_id].push(chip)
@indexes[had_chips].delete(target_id)
@indexes[had_chips + 1].push(target_id)
end
def put_to_output(source_id, target_id, chip)
had_chips = @bots[source_id].size
@bots[source_id].delete(chip)
@indexes[had_chips].delete(source_id)
@indexes[had_chips - 1].push(source_id)
@outputs[target_id] = chip
end
data.each do |line|
if line =~ /value (\d+) goes to bot (\d+)/
match = Regexp.last_match
chip, target_id = match.captures.map(&:to_i)
give_to_bot(nil, target_id, chip)
elsif line =~ /bot (\d+) gives low to (.+?) (\d+) and high to (.+?) (\d+)/
match = Regexp.last_match
source_bot = match[1].to_i
low_target_type = match[2]
low_target_id = match[3]
high_target_type = match[4]
high_target_id = match[5]
@moves[source_bot.to_i] = {
low: [low_target_type.to_sym, low_target_id.to_i],
high: [high_target_type.to_sym, high_target_id.to_i]
}
end
end
while @indexes[2].size > 0
source_id = @indexes[2][0]
low_chip, high_chip = @bots[source_id].sort
if low_chip == @target_low_chip && high_chip == @target_high_chip
puts source_id
end
low = @moves[source_id][:low]
high = @moves[source_id][:high]
if low[0] == :bot
target_id = low[1]
give_to_bot(source_id, target_id, low_chip)
else
target_id = low[1]
put_to_output(source_id, target_id, low_chip)
end
if high[0] == :bot
target_id = high[1]
give_to_bot(source_id, target_id, high_chip)
else
target_id = high[1]
put_to_output(source_id, target_id, high_chip)
end
end
# Part B
puts @outputs[0..2].reduce(1) { |product, bin| product * bin }
In this program we maintain @bots
array that keeps track of what chips bots currently hold. @indexes
hash keeps track which bots has 0, 1 or 2 chips. @outputs
array keeps track of values that were put to output.
Then we have helper methods give_to_bot
which updates all those arrays accordingly and put_to_output
is doing the same when we need to put chip to output. Because we are modifying 3 different arrays or hashes it is crucial to implement it correctly.
In the end we just read the input and execute specified commands. If we compare values 17 and 61 we can output bot number.
In second part we just need to multiple values in outputs 0, 1 and 2. I added code for that in the solution for first part.