Solution to problem 14 part 2 in Python

This commit is contained in:
David Doblas Jiménez 2021-12-23 11:10:52 +01:00
parent 5204e362c1
commit 8d8622b464

View File

@ -86,5 +86,114 @@ def part_1() -> None:
print(f"The sum of all values in memory is {values_in_memory}")
# --- Part Two ---
# For some reason, the sea port's computer system still can't communicate with
# your ferry's docking program. It must be using version 2 of the decoder chip!
# A version 2 decoder chip doesn't modify the values being written at all.
# Instead, it acts as a memory address decoder. 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!
# For example, consider the following program:
# mask = 000000000000000000000000000000X1001X
# mem[42] = 100
# mask = 00000000000000000000000000000000X0XX
# mem[26] = 1
# When this program goes to write to memory address 42, it first applies the
# bitmask:
# address: 000000000000000000000000000000101010 (decimal 42)
# mask: 000000000000000000000000000000X1001X
# result: 000000000000000000000000000000X1101X
# After applying the mask, four bits are overwritten, three of which are
# different, and two of which are floating. Floating bits take on every
# possible combination of values; with two floating bits, four actual memory
# addresses are written:
# 000000000000000000000000000000011010 (decimal 26)
# 000000000000000000000000000000011011 (decimal 27)
# 000000000000000000000000000000111010 (decimal 58)
# 000000000000000000000000000000111011 (decimal 59)
# Next, the program is about to write to memory address 26 with a different
# bitmask:
# address: 000000000000000000000000000000011010 (decimal 26)
# mask: 00000000000000000000000000000000X0XX
# result: 00000000000000000000000000000001X0XX
# This results in an address with three floating bits, causing writes to eight
# memory addresses:
# 000000000000000000000000000000010000 (decimal 16)
# 000000000000000000000000000000010001 (decimal 17)
# 000000000000000000000000000000010010 (decimal 18)
# 000000000000000000000000000000010011 (decimal 19)
# 000000000000000000000000000000011000 (decimal 24)
# 000000000000000000000000000000011001 (decimal 25)
# 000000000000000000000000000000011010 (decimal 26)
# 000000000000000000000000000000011011 (decimal 27)
# The entire 36-bit address space still begins initialized to the value 0 at
# every address, and you still need the sum of all values left in memory at the
# end of the program. In this example, the sum is 208.
# Execute the initialization program using an emulator for a version 2 decoder
# chip. What is the sum of all values left in memory after it completes?
def get_indexes(mask: str) -> list[int]:
try:
firstx = mask.index("X")
return get_indexes(
mask[:firstx] + "0" + mask[firstx + 1 :]
) + get_indexes(mask[:firstx] + "1" + mask[firstx + 1 :])
except ValueError:
return [int(mask, 2)]
def part_2() -> None:
memory = {}
for instruction in instructions:
if instruction.startswith("mask"):
mask = instruction.split(" ")[2]
elif instruction.startswith("mem"):
idx = int(instruction.split("[")[1].split("]")[0])
val = int(instruction.split(" ")[2])
idx_mask = ""
# pad with 0s (up to 36) the index
for m, i in zip(mask, f"{idx:036b}"):
if m == "0":
# do not change the bit value
idx_mask += i
elif m == "1" or m == "X":
idx_mask += m
idxs = get_indexes(idx_mask)
for idx in idxs:
memory[idx] = val
values_in_memory = sum([val for val in memory.values()])
print(f"The sum of all values in memory is {values_in_memory}")
if __name__ == "__main__":
part_1()
part_2()