From dbf1a23640cf3433f699c86b557d7e05658b4644 Mon Sep 17 00:00:00 2001 From: Stefan Harmuth Date: Sun, 16 Mar 2025 11:34:37 +0100 Subject: [PATCH] day23 - unoptimized --- asembunny.py | 87 +++++++++++++++++++++++++++++++++++++++++++++ day12.py | 62 ++------------------------------ day23.py | 30 ++++++++++++++++ inputs/input23 | 26 ++++++++++++++ inputs/input23_test | 7 ++++ 5 files changed, 153 insertions(+), 59 deletions(-) create mode 100644 asembunny.py create mode 100644 day23.py create mode 100644 inputs/input23 create mode 100644 inputs/input23_test diff --git a/asembunny.py b/asembunny.py new file mode 100644 index 0000000..2f956af --- /dev/null +++ b/asembunny.py @@ -0,0 +1,87 @@ +from enum import Enum + + +class Command(str, Enum): + COPY = "cpy" + INCREASE = "inc" + DECREASE = "dec" + JUMP_NON_ZERO = "jnz" + TOGGLE = "tgl" + + +class Computer: + def __init__( + self, code: list[tuple[Command, str | int, ...]], reg_a: int = 0, reg_b: int = 0, reg_c: int = 0, reg_d: int = 0 + ): + self.reg = { + "a": reg_a, + "b": reg_b, + "c": reg_c, + "d": reg_d, + } + self.code = code + self.instr_ptr = 0 + + def get_value(self, source: int | str) -> int: + if isinstance(source, int): + return source + + if source not in "abcd": + raise ValueError(f"Invalid source: {source}") + + return self.reg[source] + + def run(self): + while self.instr_ptr < len(self.code): + cmd, *args = self.code[self.instr_ptr] + if cmd == Command.COPY: + if isinstance(args[0], int): + self.reg[args[1]] = args[0] + else: + self.reg[args[1]] = self.reg[args[0]] + self.instr_ptr += 1 + elif cmd == Command.INCREASE: + self.reg[args[0]] += 1 + self.instr_ptr += 1 + elif cmd == Command.DECREASE: + self.reg[args[0]] -= 1 + self.instr_ptr += 1 + elif cmd == Command.JUMP_NON_ZERO: + if isinstance(args[0], int): + check = args[0] + else: + check = self.reg[args[0]] + if check: + self.instr_ptr += self.get_value(args[1]) + else: + self.instr_ptr += 1 + elif cmd == Command.TOGGLE: + target = self.instr_ptr + self.reg[args[0]] + if target >= len(self.code) or target < 0: + self.instr_ptr += 1 + continue + + target_instr = self.code[target] + if len(target_instr) == 2: + if target_instr[0] != Command.INCREASE: + self.code[target] = (Command.INCREASE, target_instr[1]) + else: + self.code[target] = (Command.DECREASE, target_instr[1]) + else: + if target_instr[0] != Command.JUMP_NON_ZERO: + self.code[target] = (Command.JUMP_NON_ZERO, *target_instr[1:]) + else: + self.code[target] = (Command.COPY, *target_instr[1:]) + + self.instr_ptr += 1 + + +def parse_assembunny_code(code_lines: list[str]) -> list[tuple[Command, str | int, ...]]: + code = [] + for line in code_lines: + args = line.split() + cmd = Command(args[0]) + args = [int(arg) if arg not in "abcd" else arg for arg in args[1:]] + code.append((cmd, *args)) + + return code diff --git a/day12.py b/day12.py index 46d3ac7..72e48ee 100644 --- a/day12.py +++ b/day12.py @@ -1,52 +1,6 @@ -from enum import Enum from tools.aoc import AOCDay from typing import Any - - -class Command(str, Enum): - COPY = "cpy" - INCREASE = "inc" - DECREASE = "dec" - JUMP_NON_ZERO = "jnz" - - -class Computer: - def __init__( - self, code: list[tuple[Command, str | int, ...]], reg_a: int = 0, reg_b: int = 0, reg_c: int = 0, reg_d: int = 0 - ): - self.reg = { - "a": reg_a, - "b": reg_b, - "c": reg_c, - "d": reg_d, - } - self.code = code - self.instr_ptr = 0 - - def run(self): - while self.instr_ptr < len(self.code): - cmd, *args = self.code[self.instr_ptr] - if cmd == Command.COPY: - if isinstance(args[0], int): - self.reg[args[1]] = args[0] - else: - self.reg[args[1]] = self.reg[args[0]] - self.instr_ptr += 1 - elif cmd == Command.INCREASE: - self.reg[args[0]] += 1 - self.instr_ptr += 1 - elif cmd == Command.DECREASE: - self.reg[args[0]] -= 1 - self.instr_ptr += 1 - elif cmd == Command.JUMP_NON_ZERO: - if isinstance(args[0], int): - check = args[0] - else: - check = self.reg[args[0]] - if check: - self.instr_ptr += args[1] - else: - self.instr_ptr += 1 +from asembunny import parse_assembunny_code, Computer class Day(AOCDay): @@ -60,23 +14,13 @@ class Day(AOCDay): ], ] - def parse_input(self) -> list[tuple[Command, str | int, ...]]: - code = [] - for line in self.getInput(): - args = line.split() - cmd = Command(args[0]) - args = [int(arg) if arg not in "abcd" else arg for arg in args[1:]] - code.append((cmd, *args)) - - return code - def part1(self) -> Any: - computer = Computer(code=self.parse_input()) + computer = Computer(code=parse_assembunny_code(self.getInput())) computer.run() return computer.reg["a"] def part2(self) -> Any: - computer = Computer(code=self.parse_input(), reg_c=1) + computer = Computer(code=parse_assembunny_code(self.getInput()), reg_a=1) computer.run() return computer.reg["a"] diff --git a/day23.py b/day23.py new file mode 100644 index 0000000..fffb54a --- /dev/null +++ b/day23.py @@ -0,0 +1,30 @@ +from asembunny import Computer, parse_assembunny_code +from tools.aoc import AOCDay +from typing import Any + + +class Day(AOCDay): + inputs = [ + [ + (3, "input23_test"), + (11004, "input23"), + ], + [ + (479007564, "input23"), + ], + ] + + def part1(self) -> Any: + computer = Computer(parse_assembunny_code(self.getInput()), reg_a=7 if not self.is_test() else 0) + computer.run() + return computer.reg["a"] + + def part2(self) -> Any: + computer = Computer(parse_assembunny_code(self.getInput()), reg_a=12) + computer.run() + return computer.reg["a"] + + +if __name__ == "__main__": + day = Day(2016, 23) + day.run(verbose=True) diff --git a/inputs/input23 b/inputs/input23 new file mode 100644 index 0000000..25384ff --- /dev/null +++ b/inputs/input23 @@ -0,0 +1,26 @@ +cpy a b +dec b +cpy a d +cpy 0 a +cpy b c +inc a +dec c +jnz c -2 +dec d +jnz d -5 +dec b +cpy b c +cpy c d +dec d +inc c +jnz d -2 +tgl c +cpy -16 c +jnz 1 c +cpy 84 c +jnz 71 d +inc a +inc d +jnz d -2 +inc c +jnz c -5 diff --git a/inputs/input23_test b/inputs/input23_test new file mode 100644 index 0000000..95ee4aa --- /dev/null +++ b/inputs/input23_test @@ -0,0 +1,7 @@ +cpy 2 a +tgl a +tgl a +tgl a +cpy 1 a +dec a +dec a \ No newline at end of file