From 1c0830064ddb49dce6eac2e5acb0500c7876fcc3 Mon Sep 17 00:00:00 2001 From: Joshua Seigler Date: Fri, 20 Dec 2024 10:25:30 -0500 Subject: [PATCH] day 20 --- .aocrunner.json | 17 ++++---- README.md | 12 +++--- src/day20/README.md | 9 +++++ src/day20/index.ts | 93 +++++++++++++++++++++++++++++++++++++++++++ src/template/index.ts | 22 ++++++++++ 5 files changed, 140 insertions(+), 13 deletions(-) create mode 100644 src/day20/README.md create mode 100644 src/day20/index.ts diff --git a/.aocrunner.json b/.aocrunner.json index 0f26a73..2e033cb 100644 --- a/.aocrunner.json +++ b/.aocrunner.json @@ -300,16 +300,19 @@ }, { "part1": { - "solved": false, - "result": null, - "attempts": [], - "time": null + "solved": true, + "result": "1327", + "attempts": [ + "19031047", + "1341" + ], + "time": 396.636417 }, "part2": { - "solved": false, - "result": null, + "solved": true, + "result": "985737", "attempts": [], - "time": null + "time": 409.185083 } }, { diff --git a/README.md b/README.md index c88bd37..cb98968 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ [![Day](https://badgen.net/badge/17/%E2%98%85%E2%98%85/green)](src/day17) [![Day](https://badgen.net/badge/18/%E2%98%85%E2%98%85/green)](src/day18) [![Day](https://badgen.net/badge/19/%E2%98%85%E2%98%85/green)](src/day19) -![Day](https://badgen.net/badge/20/%E2%98%86%E2%98%86/gray) +[![Day](https://badgen.net/badge/20/%E2%98%85%E2%98%85/green)](src/day20) ![Day](https://badgen.net/badge/21/%E2%98%86%E2%98%86/gray) ![Day](https://badgen.net/badge/22/%E2%98%86%E2%98%86/gray) ![Day](https://badgen.net/badge/23/%E2%98%86%E2%98%86/gray) @@ -202,9 +202,9 @@ Both parts: 173.084ms ``` Day 20 -Time part 1: - -Time part 2: - -Both parts: - +Time part 1: 394.252ms +Time part 2: 407.336ms +Both parts: 801.588ms ``` ``` @@ -243,8 +243,8 @@ Both parts: - ``` ``` -Total stars: 38/50 -Total time: 176482.246ms +Total stars: 40/50 +Total time: 177283.834ms ``` diff --git a/src/day20/README.md b/src/day20/README.md new file mode 100644 index 0000000..08b5a53 --- /dev/null +++ b/src/day20/README.md @@ -0,0 +1,9 @@ +# 🎄 Advent of Code 2024 - day 20 🎄 + +## Info + +Task description: [link](https://adventofcode.com/2024/day/20) + +## Notes + +... \ No newline at end of file diff --git a/src/day20/index.ts b/src/day20/index.ts new file mode 100644 index 0000000..8e2f75e --- /dev/null +++ b/src/day20/index.ts @@ -0,0 +1,93 @@ +import run from "aocrunner" + +const ints = (line: string) => [...line.matchAll(/\d+/g)].map(Number) +const parseInput = (rawInput: string) => + rawInput.split("\n").map((line) => line.split("")) + +const deltas: [Coord, Coord, Coord, Coord] = [ + [0, 1], // right + [1, 0], // down + [0, -1], // left + [-1, 0], // up +] + +type Coord = [number, number] + +function manhattan([ar, ac]: Coord, [br, bc]: Coord) { + return Math.abs(ar - br) + Math.abs(ac - bc) +} + +const part1 = (rawInput: string, mustSave = 100, maxCheat = 2) => { + const input = parseInput(rawInput) + let S: Coord + let E: Coord + input.forEach((row, r) => { + row.forEach((cell, c) => { + if (cell === "S") S = [r, c] + if (cell === "E") E = [r, c] + }) + }) + let [r, c] = S + const path: Coord[] = [S] + while (true) { + const neighbors = deltas.map(([dr, dc]) => [r + dr, c + dc]) + const next = neighbors.find(([nr, nc]) => { + if (input[nr][nc] === "#") return false + return path.find(([pr, pc]) => pr === nr && pc === nc) === undefined + }) + if (next === undefined) break + ;[r, c] = next + path.push(next) + } + let total = 0 + for (let i = 0; i < path.length; i++) { + for (let j = i + mustSave; j < path.length; j++) { + const distance = manhattan(path[i], path[j]) + if (distance <= maxCheat && j - i - distance >= mustSave) { + total++ + } + } + } + return total +} + +const part2 = (rawInput: string) => { + return part1(rawInput, 100, 20) +} + +run({ + part1: { + tests: [ + // { + // input: ``, + // expected: "", + // }, + ], + solution: part1, + }, + part2: { + tests: [ + // { + // input: ``, + // expected: "", + // }, + ], + solution: part2, + }, + trimTestInputs: true, + onlyTests: false, +}) + +function bold(text: string) { + return `\x1b[44;37;1m${text}\x1b[0m` +} + +function memoize( + fn: (...args: T) => U, +): (...args: T) => U { + const cache = {} // Saves the values + return (...args) => { + const key = args.join("\n") + return cache[key] ?? (cache[key] = fn(...args)) + } +} diff --git a/src/template/index.ts b/src/template/index.ts index c1ec769..872d7e9 100644 --- a/src/template/index.ts +++ b/src/template/index.ts @@ -1,7 +1,17 @@ import run from "aocrunner" +const ints = (line: string) => [...line.matchAll(/\d+/g)].map(Number) const parseInput = (rawInput: string) => rawInput +const deltas: [Coord, Coord, Coord, Coord] = [ + [ 0, 1], // right + [ 1, 0], // down + [ 0, -1], // left + [-1, 0], // up +] + +type Coord = [number, number] + const part1 = (rawInput: string) => { const input = parseInput(rawInput) @@ -36,3 +46,15 @@ run({ trimTestInputs: true, onlyTests: false, }) + +function bold(text: string) { + return `\x1b[44;37;1m${text}\x1b[0m` +} + +function memoize(fn: (...args: T) => U): (...args: T) => U { + const cache = {} // Saves the values + return (...args) => { + const key = args.join('\n') + return cache[key] ?? (cache[key] = fn(...args)) + } +}