diff --git a/.aoc_tiles/tiles/2024/17.png b/.aoc_tiles/tiles/2024/17.png new file mode 100644 index 0000000..9d2f7b6 Binary files /dev/null and b/.aoc_tiles/tiles/2024/17.png differ diff --git a/2024/17/example b/2024/17/example new file mode 100644 index 0000000..f09839b --- /dev/null +++ b/2024/17/example @@ -0,0 +1,5 @@ +Register A: 729 +Register B: 0 +Register C: 0 + +Program: 0,1,5,4,3,0 diff --git a/2024/17/example_p2 b/2024/17/example_p2 new file mode 100644 index 0000000..4a91c26 --- /dev/null +++ b/2024/17/example_p2 @@ -0,0 +1,5 @@ +Register A: 2024 +Register B: 0 +Register C: 0 + +Program: 0,3,5,4,3,0 diff --git a/2024/17/script.py b/2024/17/script.py new file mode 100644 index 0000000..cb8f916 --- /dev/null +++ b/2024/17/script.py @@ -0,0 +1,82 @@ +from GhostyUtils import aoc +from dataclasses import dataclass +import operator +from typing import Callable + + +@dataclass +class Registers: + A: int + B: int + C: int + + +def combo(operand: int, regs: Registers) -> int: + match operand: + case 0: return 0 + case 1: return 1 + case 2: return 2 + case 3: return 3 + case 4: return regs.A + case 5: return regs.B + case 6: return regs.C + case 7: assert False + + +def process(program: list[int], regs: Registers, output: Callable): + i_ptr = 0 + + while True: + if i_ptr >= len(program): + break + + instr = program[i_ptr] + operand = program[i_ptr+1] + + match instr: + case 0: # adv (A division by combo operand, store in A) + regs.A = regs.A // (2 ** combo(operand, regs)) + i_ptr += 2 + case 1: # bxl (bitwise xor of B and literal operand, store in B) + regs.B = operator.xor(regs.B, operand) + i_ptr += 2 + case 2: # bst (combo operand modulo 8, store in B) + regs.B = combo(operand, regs) % 8 + i_ptr += 2 + case 3: # jnz (jump to literal operand if A non-zero) + if regs.A == 0: + i_ptr += 2 + else: + i_ptr = operand + case 4: # bxc (bitwise xor of B and C, store in B) + regs.B = operator.xor(regs.B, regs.C) + i_ptr += 2 + case 5: # out (output combo operand modulo 8) + output(combo(operand, regs) % 8) + i_ptr += 2 + case 6: # bdv (A division by combo operand, store in B) + regs.B = regs.A // (2 ** combo(operand, regs)) + i_ptr += 2 + case 7: # cdv (A division by combo operand, store in C) + regs.C = regs.A // (2 ** combo(operand, regs)) + i_ptr += 2 + + +def read_regs(registers: str) -> Registers: + a, b, c = (r.split(': ') for r in registers.splitlines()) + regs = Registers(int(a[1]), int(b[1]), int(c[1])) + return regs + + +def main(): + registers, program = (section.strip() for section in aoc.read_sections()) + regs = read_regs(registers) + program = list(map(int, program.split(': ')[1].split(','))) + + output = [] + process(program, regs, output=output.append) + print(f"p1: {','.join(map(str, output))}") + + +if __name__ == "__main__": + main() diff --git a/README.md b/README.md index c7a66a2..7c3ef39 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,10 @@ My solutions to the yearly Advents of Code

- Advent of Code - 192/482 ⭐ + Advent of Code - 193/484 ⭐

- 2024 - 31 ⭐ - Python + 2024 - 32 ⭐ - Python

@@ -56,6 +56,9 @@ My solutions to the yearly Advents of Code + + +

2023 - 47 ⭐ - Python