From 4f6e500b7a10e7591b351ec7b7d182984e09b8fb Mon Sep 17 00:00:00 2001 From: Joshua Seigler Date: Tue, 17 Dec 2024 11:20:59 -0500 Subject: [PATCH] day 17 part 2, wow --- .aocrunner.json | 10 ++-- README.md | 12 ++--- src/day17/index.ts | 118 ++++++++++++++++++++++++--------------------- 3 files changed, 74 insertions(+), 66 deletions(-) diff --git a/.aocrunner.json b/.aocrunner.json index 6d9ae99..9b2fcb4 100644 --- a/.aocrunner.json +++ b/.aocrunner.json @@ -254,17 +254,17 @@ { "part1": { "solved": true, - "result": null, + "result": "1,5,0,1,7,4,1,0,3", "attempts": [ "1,4,0,1,1,0,1,0,3" ], - "time": null + "time": 0.057416 }, "part2": { - "solved": false, - "result": null, + "solved": true, + "result": "47910079998866", "attempts": [], - "time": null + "time": 8772.936208 } }, { diff --git a/README.md b/README.md index 5c742f2..88992c9 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ [![Day](https://badgen.net/badge/14/%E2%98%85%E2%98%86/yellow)](src/day14) [![Day](https://badgen.net/badge/15/%E2%98%85%E2%98%85/green)](src/day15) [![Day](https://badgen.net/badge/16/%E2%98%85%E2%98%85/green)](src/day16) -[![Day](https://badgen.net/badge/17/%E2%98%85%E2%98%86/yellow)](src/day17) +[![Day](https://badgen.net/badge/17/%E2%98%85%E2%98%85/green)](src/day17) ![Day](https://badgen.net/badge/18/%E2%98%86%E2%98%86/gray) ![Day](https://badgen.net/badge/19/%E2%98%86%E2%98%86/gray) ![Day](https://badgen.net/badge/20/%E2%98%86%E2%98%86/gray) @@ -181,9 +181,9 @@ Both parts: 132.546ms ``` Day 17 -Time part 1: 0.064ms -Time part 2: - -Both parts: 0.064ms +Time part 1: - +Time part 2: 8693.239ms +Both parts: 8693.239ms ``` ``` @@ -243,8 +243,8 @@ Both parts: - ``` ``` -Total stars: 32/50 -Total time: 150841.277ms +Total stars: 33/50 +Total time: 159534.453ms ``` diff --git a/src/day17/index.ts b/src/day17/index.ts index 560a0e4..10e93ac 100644 --- a/src/day17/index.ts +++ b/src/day17/index.ts @@ -1,10 +1,10 @@ import run from "aocrunner" const parseInput = (rawInput: string) => { - const [registers, program] = rawInput.split('\n\n') + const [registers, program] = rawInput.split("\n\n") return { - registers: registers.split('\n').map(r => BigInt(r.split(": ")[1])), - program: program.split(': ')[1].split(',').map(Number) + registers: registers.split("\n").map((r) => BigInt(r.split(": ")[1])), + program: program.split(": ")[1].split(",").map(Number), } } @@ -12,70 +12,65 @@ const mod = (a: bigint, b: bigint) => ((a % b) + b) % b const explainProgram = (program: number[]) => { let explanation = "" - const ops = [ - x => `A = A >> ${combo(x)}`, - x => `B = B XOR ${x}`, - x => `B = ${combo(x)} % 8`, - x => `GOTO ${x}`, - x => `B = B XOR C`, - x => `Output ${combo(x)} % 8`, - x => `B = B >> ${combo(x)}`, - x => `C = C >> ${combo(x)}`, + const ops: ((x: number) => void)[] = [ + (x) => `A = A >> ${combo(x)}`, + (x) => `B = B XOR ${x}`, + (x) => `B = ${combo(x)} % 8`, + (x) => `GOTO ${x}`, + () => `B = B XOR C`, + (x) => `Output ${combo(x)} % 8`, + (x) => `B = B >> ${combo(x)}`, + (x) => `C = C >> ${combo(x)}`, ] - const combo = x => "0123ABC"[x] + const combo = (x: number) => "0123ABC"[x] for (let i = 0; i < program.length; i += 2) { - const op = ops[program[i]](program[i+1]) + const op = ops[program[i]](program[i + 1]) explanation += `${i}: ${op}\n` } - return explanation.trim() + return explanation } const execute = (registers: bigint[], program: number[]) => { - let seenStates = new Set() let [a, b, c] = registers let pointer = 0 const output: number[] = [] const getCombo = (n: number) => [0n, 1n, 2n, 3n, a, b, c][n] const ops: ((operand: number) => void)[] = [ - n => { // adv + function adv(n) { a = a >> getCombo(n) pointer += 2 }, - n => { // bxl + function bxl(n) { b = b ^ BigInt(n) pointer += 2 }, - n => { // bst + function bst(n) { b = mod(getCombo(n), 8n) pointer += 2 }, - n => { // jnz + function jnz(n) { pointer = a === 0n ? pointer + 2 : n }, - n => { // bxc + function bxc(_) { b = b ^ c pointer += 2 }, - n => { // out + function out(n) { output.push(Number(mod(getCombo(n), 8n))) pointer += 2 }, - n => { // bdv + function bdv(n) { b = a >> getCombo(n) pointer += 2 }, - n => { // cdv + function cdv(n) { c = a >> getCombo(n) pointer += 2 }, ] while (true) { - const thisState = [a,b,c,pointer].join() - if (seenStates.has(thisState)) { - return 'LOOP' - } if (pointer >= program.length) { - return output.join() + return output } const opcode = program[pointer] const operand = program[pointer + 1] @@ -85,40 +80,53 @@ const execute = (registers: bigint[], program: number[]) => { const part1 = (rawInput: string) => { const { registers, program } = parseInput(rawInput) - return execute(registers, program) + return execute(registers, program).join() } - const part2 = (rawInput: string) => { - const { registers: [_a, b, c], program } = parseInput(rawInput) + const { + registers: [_a, b, c], + program, + } = parseInput(rawInput) console.log(explainProgram(program)) - // const target = program.join() - // let i = 1n - // while (true) { - // const result = execute([i, b, c], program) - // if (result.length < target.length) i *= 2n - // if (result === target) { - // return i - // } - // console.log(`${i} ${result}`) - // i += 1n - // } + + let i = 0n + let found = 0 + while (true) { + const result = execute([i, b, c], program) + console.log(`${i} ${result.join()}`) + let matchCount = 0 + for (let j = 0; j < result.length; j++) { + if (result[result.length - 1 - j] === program[program.length - 1 - j]) { + matchCount++ + } else break + } + if (matchCount === program.length) { + return Number(i) + } + if (matchCount > found) { + i = i << (3n * BigInt(matchCount - found)) + found = matchCount + } else { + i++ + } + } } run({ -// part1: { -// tests: [ -// { -// input: `Register A: 729 -// Register B: 0 -// Register C: 0 + part1: { + tests: [ + { + input: `Register A: 729 +Register B: 0 +Register C: 0 -// Program: 0,1,5,4,3,0`, -// expected: `4,6,3,5,6,3,5,2,1,0`, -// }, -// ], -// solution: part1, -// }, +Program: 0,1,5,4,3,0`, + expected: `4,6,3,5,6,3,5,2,1,0`, + }, + ], + solution: part1, + }, part2: { tests: [ {