diff --git a/2024/17/example.txt b/2024/17/example.txt new file mode 100644 index 0000000..36fbf8d --- /dev/null +++ b/2024/17/example.txt @@ -0,0 +1,5 @@ +Register A: 729 +Register B: 0 +Register C: 0 + +Program: 0,1,5,4,3,0 \ No newline at end of file diff --git a/2024/17/index.test.ts b/2024/17/index.test.ts new file mode 100644 index 0000000..37df3b4 --- /dev/null +++ b/2024/17/index.test.ts @@ -0,0 +1,33 @@ +import { expect, describe, test } from "bun:test"; +import { part1, part2 } from "."; +import { getInputs } from "../../utils/get-inputs"; + +const { exampleInput, puzzleInput } = await getInputs("2024/17"); + +describe("part 1", () => { + test("example", () => { + expect(part1(exampleInput)).toBe("4,6,3,5,6,3,5,2,1,0"); + }); + + test("puzzle", () => { + expect(part1(puzzleInput)).toBe("7,1,3,4,1,2,6,7,1"); + }); +}); + +const exampleInputForPart2 = ` +Register A: 2024 +Register B: 0 +Register C: 0 + +Program: 0,3,5,4,3,0 +`.trim(); + +describe("part 2", () => { + test("example", () => { + expect(part2(exampleInputForPart2)).toBe("117440"); + }); + + test("puzzle", () => { + expect(part2(puzzleInput)).toBe("109019476330651"); + }); +}); diff --git a/2024/17/index.ts b/2024/17/index.ts new file mode 100644 index 0000000..08334d8 --- /dev/null +++ b/2024/17/index.ts @@ -0,0 +1,127 @@ +import { timePart1, timePart2 } from "../../utils/time-part"; + +const parseInput = (input: string) => { + const [registers, program] = input.split("\n\n"); + + const [a, b, c] = registers + .split("\n") + .map((register) => BigInt(register.split(": ")[1])); + + return { + registers: { a, b, c }, + program: program.split(": ")[1].split(",").map(BigInt), + }; +}; + +const modulo = (a: bigint, b: bigint) => ((a % b) + b) % b; + +const getComboOperand = ( + literalOperand: bigint, + registers: ReturnType["registers"] +) => { + if (literalOperand === 4n) return registers.a; + if (literalOperand === 5n) return registers.b; + if (literalOperand === 6n) return registers.c; + + return literalOperand; +}; + +const runProgram = ({ program, registers }: ReturnType) => { + let output: bigint[] = []; + + let i = 0; + while (true) { + if (i >= program.length) { + break; + } + + const opcode = program[i]; + const operandIndex = i + 1; + + if (operandIndex >= program.length) { + break; + } + + const literalOperand = program[operandIndex]; + const comboOperand = getComboOperand(literalOperand, registers); + + // adv + if (opcode === 0n) { + registers.a = registers.a / 2n ** comboOperand; + } + + // bxl + if (opcode === 1n) { + registers.b = registers.b ^ literalOperand; + } + + // bst + if (opcode === 2n) { + registers.b = modulo(comboOperand, 8n); + } + + // jnz + if (opcode === 3n && registers.a !== 0n) { + i = Number(literalOperand); + continue; + } + + // bxc + if (opcode === 4n) { + registers.b = registers.b ^ registers.c; + } + + // out + if (opcode === 5n) { + output.push(modulo(comboOperand, 8n)); + } + + // bdv + if (opcode === 6n) { + registers.b = registers.a / 2n ** comboOperand; + } + + // cdv + if (opcode === 7n) { + registers.c = registers.a / 2n ** comboOperand; + } + + // Skip operand + i += 2; + } + + return output.join(","); +}; + +export const part1 = timePart1((input: string) => { + const { program, registers } = parseInput(input); + + return runProgram({ program, registers }); +}); + +export const part2 = timePart2((input: string) => { + const { program, registers } = parseInput(input); + + const programStr = program.join(","); + let a = 0n; + + while (true) { + const output = runProgram({ program, registers: { ...registers, a } }); + + if (output === programStr) { + break; + } + + // Once we _start_ to find a match + if (programStr.indexOf(output) + output.length === programStr.length) { + // Just increment in instances of 8-times the value of the `A` register + a = 8n * a; + + continue; + } + + a++; + } + + return a.toString(); +}); diff --git a/README.md b/README.md index 99f0e92..55df9c9 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ | Day | Part 1 | Part 2 | | :----------------------------------------: | :----: | :----: | +| [17](https://adventofcode.com/2024/day/17) | ✅ | ✅ | | [16](https://adventofcode.com/2024/day/16) | ✅ | ✅ | | [15](https://adventofcode.com/2024/day/15) | ✅ | ✅ | | [14](https://adventofcode.com/2024/day/14) | ✅ | ✅ |