Solution to problem 14 part 2 in Python
This commit is contained in:
parent
5204e362c1
commit
8d8622b464
109
src/P14.py
109
src/P14.py
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user