advent-of-code/2024/17/two_dfs.py
2024-12-25 12:59:49 +01:00

84 lines
2.3 KiB
Python

#!/usr/bin/env python3
import sys
input_file = sys.argv[1]
with open(input_file) as fd:
lines = [line.rstrip() for line in fd.readlines()]
original_B = int(lines[1].split(":")[1])
original_C = int(lines[2].split(":")[1])
program = [int(p) for p in lines[4].split(":")[1].split(",")]
def output_given_A(A: int) -> list[int]:
instruction_pointer = 0
B = original_B
C = original_C
output: list[int] = list()
while instruction_pointer in range(len(program)):
instruction = program[instruction_pointer]
literal_operator = program[instruction_pointer + 1]
if instruction == 1:
B = B ^ literal_operator
elif instruction == 3:
if A != 0:
instruction_pointer = literal_operator
continue
elif instruction == 4:
B = B ^ C
else:
combined_operator = literal_operator
if literal_operator == 4:
combined_operator = A
elif literal_operator == 5:
combined_operator = B
elif literal_operator == 6:
combined_operator = C
if instruction == 2:
B = combined_operator % 8
elif instruction == 5:
output.append(combined_operator % 8)
else:
trunc_div = A >> combined_operator
if instruction == 0:
A = trunc_div
elif instruction == 6:
B = trunc_div
else:
C = trunc_div
instruction_pointer += 2
return output
def input_to_a(input_numbers: list[int]) -> int:
A = 0
for number in reversed(input_numbers):
A = (A << 3) + number
return A
def dig(depth: int, input_numbers: list[int]) -> int | None:
input_numbers = input_numbers.copy()
depth += 1
for i in range(8):
input_numbers[-depth] = i
A = input_to_a(input_numbers)
output_numbers = output_given_A(A)
if output_numbers[-depth:] == program[-depth:]:
if depth == len(program):
return A
res = dig(depth, input_numbers)
if res is not None:
return res
return None
print(dig(0, [0] * len(program)))