From 161bd10ca3cfc51d9b17fa16af18aa2e89292161 Mon Sep 17 00:00:00 2001 From: Stefan Harmuth Date: Wed, 18 Dec 2024 14:35:39 +0100 Subject: [PATCH] day17 - FINALLY --- day17.py | 139 +++++++++------------------------------- inputs/input17_jonathan | 5 ++ 2 files changed, 35 insertions(+), 109 deletions(-) create mode 100644 inputs/input17_jonathan diff --git a/day17.py b/day17.py index 13849b2..5db0ebe 100644 --- a/day17.py +++ b/day17.py @@ -1,5 +1,3 @@ -import math -import sys from enum import Enum from tools.aoc import AOCDay from typing import Any @@ -28,7 +26,6 @@ class Computer: self.instr_pointer = 0 self.__code = code self.code = [(OpCode(code[x]), code[x + 1]) for x in range(0, len(code), 2)] - self.check_output = False self.op = { OpCode.ADV: self.adv, OpCode.BXL: self.bxl, @@ -87,14 +84,8 @@ class Computer: def out(self, operand: int) -> None: value = self.get_combo_value(operand) % 8 - if not self.check_output: - self.instr_pointer += 1 - self.output.append(value) - elif value != self.__code[len(self.output)]: - self.instr_pointer = len(self.code) - else: - self.instr_pointer += 1 - self.output.append(value) + self.output.append(value) + self.instr_pointer += 1 def bdv(self, operand: int) -> None: self.reg_b = self.reg_a // (2 ** self.get_combo_value(operand)) @@ -107,25 +98,31 @@ class Computer: def get_output(self) -> str: return ",".join(str(x) for x in self.output) - def run_code(self) -> None: + def run(self, init_a: int = None) -> str: + self.reset() + if init_a is not None: + self.reg_a = init_a + while self.instr_pointer < len(self.code): - # print("Exec", self.instr_pointer) op_code, operand = self.code[self.instr_pointer] self.op[op_code](operand) + return self.get_output() + class Day(AOCDay): inputs = [ [ ("4,6,3,5,6,3,5,2,1,0", "input17_test"), ("7,1,2,3,2,6,7,2,5", "input17_neil"), + ("1,7,6,5,1,0,5,0,7", "input17_dennis"), ("1,6,3,6,5,6,5,1,7", "input17"), ], [ (117440, "input17_test2"), (202356708354602, "input17_neil"), (236555995274861, "input17_dennis"), - (None, "input17"), + (247839653009594, "input17"), ], ] @@ -135,111 +132,35 @@ class Day(AOCDay): def part1(self) -> Any: computer = Computer(*self.parse_input()) - computer.run_code() - return computer.get_output() + return computer.run() def part2(self) -> Any: a, b, c, prog = self.parse_input() expected_output = ",".join(str(x) for x in prog) computer = Computer(a, b, c, prog) - computer.check_output = True - def run_computer(v: int) -> str: - computer.reset() - computer.reg_a = v - computer.run_code() - return computer.get_output() - - init_a = 0 - init_reg = 0 - output = "" - bit_match = "" - bit_width = 6 - bit_add = bit_width - 1 - factor = 0 - additive = 0 - best = 0 - while output != expected_output: - init_reg = init_a * (8**factor) + additive - output = run_computer(init_reg) - - if len(output) > best and output == expected_output[: len(output)]: - # if output == expected_output[: len(output)]: - o = oct(init_reg) - if o[-bit_width:] != bit_match: - bit_match = o[-bit_width:] + def get_match_pos(a: str, b: str) -> int: + m = 0 + for x, y in zip(reversed(a), reversed(b)): + if x == y: + m += 1 else: - additive = int(bit_match, 8) - factor = bit_width - bit_width += bit_add - bit_add -= 1 - init_a = 0 + break - print( - f"{init_reg=} ({oct(init_reg)}), {factor=}, additive={oct(additive)}, {output=}, {expected_output=}" - ) - best = len(output) + return m - if init_a % 1_000_000 == 0: - print(init_a, init_reg) - init_a += 1 + num = 0 + for factor in range(len(prog)): + for i in range(8**len(prog)): + output = computer.run(num + i) + if get_match_pos(output, expected_output) == (2 * factor) + 1: + if factor < len(prog) - 1: + num = (i + num) * 8 + else: + num += i + break - print(init_a - 1, (init_a - 1) * (8**factor) + additive) - output = run_computer(init_reg) - print(output) - if output == expected_output: - return init_reg - return "" - - first = [] - for i, c in enumerate(prog): - reg_a_init = 0 - - while len(first) <= i: - computer.reset() - computer.reg_a = reg_a_init - computer.run_code() - if int(computer.get_output()[0]) == c: - first.append(reg_a_init) - - reg_a_init += 1 - - print(first) - result = 0 - for i, c in enumerate(reversed(first)): - result = result << 3 - result += c // 8 - # result = sum(((x * (8 ** i) for i, x in enumerate(first)))) - print(result) - - computer.reset() - computer.reg_a = result - computer.run_code() - print(computer.get_output()) - if computer.get_output() == expected_output: - return result - - while computer.get_output() != expected_output: - result -= 1 - computer.reset() - computer.reg_a = result - computer.run_code() - - return result - - for i in range(len(first)): - result = sum(((x * (8**i) for i, x in enumerate(first[: i + 1])))) - print("Testing ", first[: i + 1], "=", result) - computer.reset() - computer.reg_a = result - computer.run_code() - print(expected_output) - print(computer.get_output()) - - if computer.get_output() == expected_output: - return result - else: - return "" + return num if __name__ == "__main__": diff --git a/inputs/input17_jonathan b/inputs/input17_jonathan new file mode 100644 index 0000000..a9e6a42 --- /dev/null +++ b/inputs/input17_jonathan @@ -0,0 +1,5 @@ +Register A: 27334280 +Register B: 0 +Register C: 0 + +Program: 2,4,1,2,7,5,0,3,1,7,4,1,5,5,3,0 \ No newline at end of file