Skip to content

Commit 22ac990

Browse files
committed
feat: 2024 Day 17
1 parent 7f3a7b8 commit 22ac990

File tree

3 files changed

+106
-10
lines changed

3 files changed

+106
-10
lines changed

2024/day/17/part/1/solve.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
function run(a: number, b: number, c: number, program: number[]) {
1+
function run({ a, b, c }: Record<"a" | "b" | "c", bigint>, program: number[]) {
22
const output: number[] = [];
3-
function combo(operand: number) {
4-
if (operand < 4) return operand;
3+
function combo(operand: number): bigint {
54
switch (operand) {
65
case 0:
76
case 1:
87
case 2:
9-
return operand;
8+
case 3:
9+
return BigInt(operand);
1010
case 4:
1111
return a;
1212
case 5:
@@ -18,7 +18,7 @@ function run(a: number, b: number, c: number, program: number[]) {
1818
}
1919
}
2020
function div(operand: number) {
21-
return Math.trunc(a / 2 ** combo(operand));
21+
return a / 2n ** combo(operand);
2222
}
2323
for (let ip = 0; ip in program;) {
2424
const opcode = program[ip++];
@@ -28,10 +28,10 @@ function run(a: number, b: number, c: number, program: number[]) {
2828
a = div(operand);
2929
break;
3030
case 1: // bxl
31-
b = b ^ operand;
31+
b = b ^ BigInt(operand);
3232
break;
3333
case 2: // bst
34-
b = combo(operand) % 8;
34+
b = combo(operand) % 8n;
3535
break;
3636
case 3: // jnz
3737
if (a) ip = operand;
@@ -40,7 +40,7 @@ function run(a: number, b: number, c: number, program: number[]) {
4040
b ^= c;
4141
break;
4242
case 5: // out
43-
output.push(combo(operand) % 8);
43+
output.push(Number(combo(operand) % 8n));
4444
break;
4545
case 6: // bdv
4646
b = div(operand);
@@ -55,7 +55,7 @@ function run(a: number, b: number, c: number, program: number[]) {
5555

5656
export default function solve(input: string) {
5757
const [top, bottom] = input.split("\n\n");
58-
const [a, b, c] = top.matchAll(/\d+/g)!.map(([v]) => +v);
58+
const [a, b, c] = top.matchAll(/\d+/g)!.map(([v]) => BigInt(v));
5959
const program = bottom.split(": ")[1].split(",").map(Number);
60-
return run(a, b, c, program).join(",");
60+
return run({ a, b, c }, program).join(",");
6161
}

2024/day/17/part/2/solve.test.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import solve from "./solve.ts";
2+
3+
import { assertEquals } from "@std/assert";
4+
5+
Deno.test("example", () => {
6+
const input = `\
7+
Register A: 2024
8+
Register B: 0
9+
Register C: 0
10+
11+
Program: 0,3,5,4,3,0`;
12+
13+
assertEquals(solve(input), "117440");
14+
});

2024/day/17/part/2/solve.ts

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
type Registers = Record<"a" | "b" | "c", bigint>;
2+
3+
function run({ a, b, c }: Registers, program: number[]) {
4+
const output: number[] = [];
5+
function combo(operand: number): bigint {
6+
switch (operand) {
7+
case 0:
8+
case 1:
9+
case 2:
10+
case 3:
11+
return BigInt(operand);
12+
case 4:
13+
return a;
14+
case 5:
15+
return b;
16+
case 6:
17+
return c;
18+
default:
19+
throw new Error(`unsupported combo literal: ${operand}`);
20+
}
21+
}
22+
function div(operand: number) {
23+
return a / 2n ** combo(operand);
24+
}
25+
for (let ip = 0; ip in program;) {
26+
const opcode = program[ip++];
27+
const operand = program[ip++];
28+
switch (opcode) {
29+
case 0: // adv
30+
a = div(operand);
31+
break;
32+
case 1: // bxl
33+
b = b ^ BigInt(operand);
34+
break;
35+
case 2: // bst
36+
b = combo(operand) % 8n;
37+
break;
38+
case 3: // jnz
39+
if (a) ip = operand;
40+
break;
41+
case 4: // bxc
42+
b ^= c;
43+
break;
44+
case 5: // out
45+
output.push(Number(combo(operand) % 8n));
46+
break;
47+
case 6: // bdv
48+
b = div(operand);
49+
break;
50+
case 7: // cdv
51+
c = div(operand);
52+
break;
53+
}
54+
}
55+
return output;
56+
}
57+
58+
/** adapted from https://github.com/gbasov/aoc24/blob/0c8149623f7f7ccf6da1d072d439bb60136aea10/17/part2.ts */
59+
function findA(
60+
{ b, c }: Omit<Registers, "a">,
61+
program: number[],
62+
input = 0n,
63+
offset = program.length - 1,
64+
): bigint | undefined {
65+
if (offset === -1) return input;
66+
67+
for (let i = 0n; i < 8n; i++) {
68+
const a = (input << 3n) + i;
69+
const output = run({ a, b, c }, program);
70+
if (output[0] !== program.at(offset)) continue;
71+
const min = findA({ b, c }, program, a, offset - 1);
72+
if (min === undefined) continue;
73+
return min;
74+
}
75+
}
76+
77+
export default function solve(input: string) {
78+
const [top, bottom] = input.split("\n\n");
79+
const [b, c] = top.matchAll(/\d+/g)!.map(([v]) => BigInt(v));
80+
const program = bottom.split(": ")[1].split(",").map(Number);
81+
return findA({ b, c }, program)?.toString();
82+
}

0 commit comments

Comments
 (0)