Advent of Code 2020: Day 14 (Ruby solution)
Today's tasks were bit manipulation. The initialization program (your puzzle input) can either update the bitmask or write a value to memory. Values and memory addresses are both 36-bit unsigned integers.
In the first task, a bitmask is used to transform a value before writing it. A 0 or 1 overwrites the corresponding bit in the value, while an X leaves the bit in the value unchanged.
In another task, a bitmask is used to transform an address. Immediately before a value is written to memory, each bit in the bitmask modifies the corresponding bit of the destination memory address in the following way:
- If the bitmask bit is 0, the corresponding memory address bit is unchanged.
- If the bitmask bit is 1, the corresponding memory address bit is overwritten with 1.
- If the bitmask bit is X, the corresponding memory address bit is floating. A floating bit is not connected to anything and instead fluctuates unpredictably. In practice, this means the floating bits will take on all possible values, potentially causing many memory addresses to be written all at once.
This is my Ruby solution:
def int_to_bin value
value.to_i.to_s(2).rjust(36, "0")
end
def sum_mem_values file, decode_address = false
mem = {}
mask = 'X' * 36
file.each_line do |line|
command = line.split " = "
variable = command.first
address = variable.scan(/\d+/).first.to_i
value = command.last.strip
if variable == 'mask'
mask = value
elsif decode_address
address_bin = int_to_bin(address)
['0', '1'].repeated_permutation(mask.count('X')) do |x_values|
address_bin_copy = address_bin
mask.each_char.with_index do |char, index|
address_bin_copy[index] = '1' if char == '1'
address_bin_copy[index] = x_values[mask[0...index].count('X')] if char == 'X'
end
mem[address_bin_copy.to_i(2)] = value.to_i
end
else # decode value
value_bin = int_to_bin(value)
mask.each_char.with_index do |char, index|
value_bin[index] = '1' if char == '1'
value_bin[index] = '0' if char == '0'
end
mem[address] = value_bin.to_i(2)
end
end
mem.values.sum
end
file = File.read('inputs/day14.txt')
puts "First task answer: #{sum_mem_values(file)}"
puts "Second task answer: #{sum_mem_values(file, true)}"