2024 day 17 specific to me.
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Mikael CAPELLE 2024-12-17 14:28:37 +01:00
parent 4dcdab9931
commit 11e32ddfda

View File

@ -11,7 +11,7 @@ def combo(registers: dict[str, int], operand: int):
def adv(registers: dict[str, int], operand: int) -> int | None: def adv(registers: dict[str, int], operand: int) -> int | None:
registers["A"] = registers["A"] // (2 ** combo(registers, operand)) registers["A"] = registers["A"] >> combo(registers, operand)
def bxl(registers: dict[str, int], operand: int) -> int | None: def bxl(registers: dict[str, int], operand: int) -> int | None:
@ -32,11 +32,11 @@ def bxc(registers: dict[str, int], operand: int) -> int | None:
def bdv(registers: dict[str, int], operand: int) -> int | None: def bdv(registers: dict[str, int], operand: int) -> int | None:
registers["B"] = registers["A"] // (2 ** combo(registers, operand)) registers["B"] = registers["A"] >> combo(registers, operand)
def cdv(registers: dict[str, int], operand: int) -> int | None: def cdv(registers: dict[str, int], operand: int) -> int | None:
registers["C"] = registers["A"] // (2 ** combo(registers, operand)) registers["C"] = registers["A"] >> combo(registers, operand)
def run(registers: dict[str, int], program: list[int]): def run(registers: dict[str, int], program: list[int]):
@ -47,30 +47,6 @@ def run(registers: dict[str, int], program: list[int]):
instructions = [adv, bxl, bst, jnz, bxc, out, bdv, cdv] instructions = [adv, bxl, bst, jnz, bxc, out, bdv, cdv]
u = {
adv: "A = A // (2 ** {})",
bxl: "B = B ^ {}",
bst: "B = {} % 8",
jnz: "JMP {}",
bxc: "B = B ^ C",
out: "OUT {}",
bdv: "B = A // (2 ** {})",
cdv: "C = A // (2 ** {})",
}
for index in range(0, len(program), 2):
print(
u[instructions[program[index]]].format(
""
if program[index] == 4
else (
program[index + 1]
if program[index] in (1, 3) or program[index + 1] < 4
else "ABC"[program[index + 1] - 4]
)
),
)
index = 0 index = 0
while index < len(program): while index < len(program):
instruction, operand = instructions[program[index]], program[index + 1] instruction, operand = instructions[program[index]], program[index + 1]
@ -96,12 +72,37 @@ class Solver(BaseSolver):
} }
program = [int(c) for c in program_s.split(":")[1].strip().split(",")] program = [int(c) for c in program_s.split(":")[1].strip().split(",")]
print(f"program ({len(program)}):", ",".join(map(str, program))) self.logger.info(f"program ({len(program)}): " + ",".join(map(str, program)))
instruction_s = [
"A = A >> {}",
"B = B ^ {}",
"B = {} % 8",
"JMP {}",
"B = B ^ C",
"OUT {} % 8",
"B = A >> {}",
"C = A >> {}",
]
self.logger.info("PROGRAM:")
for index in range(0, len(program), 2):
self.logger.info(
instruction_s[program[index]].format(
""
if program[index] == 4
else (
program[index + 1]
if program[index] in (1, 3) or program[index + 1] < 4
else "ABC"[program[index + 1] - 4]
)
),
)
yield ",".join(map(str, run(registers.copy(), program))) yield ",".join(map(str, run(registers.copy(), program)))
out_index = next(i for i in range(0, len(program), 2) if program[i] == 5) # out_index = next(i for i in range(0, len(program), 2) if program[i] == 5)
out_register = "ABC"[program[out_index + 1] - 4] # out_register = "ABC"[program[out_index + 1] - 4]
# there is only one jump instruction and it goes back to the beginning of the # there is only one jump instruction and it goes back to the beginning of the
# program # program
@ -112,5 +113,18 @@ class Solver(BaseSolver):
and program[-1] == 0 and program[-1] == 0
) )
for value in program: valid: list[int] = [0]
print(value, f"{out_register} must equal {value | 4}") for p in reversed(program):
new_valid: list[int] = []
for v in valid:
a_high = v << 3
for a_low in range(0, 2**3):
a = a_high | a_low
b = (((a % 8) ^ 7) ^ (a >> ((a % 8) ^ 7))) ^ 4
if b % 8 == p:
new_valid.append(a)
valid = new_valid
assert run(registers | {"A": min(valid)}, program) == program
yield min(valid)