Skip to content

Commit f9cb7ad

Browse files
committed
Day 20 part 1
1 parent e983177 commit f9cb7ad

File tree

2 files changed

+108
-5
lines changed

2 files changed

+108
-5
lines changed

2024/Day_20/README.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,70 @@ In this example, the total number of cheats (grouped by the amount of time they
136136
- There is one cheat that saves 64 picoseconds.
137137

138138
You aren't sure what the conditions of the racetrack will be like, so to give yourself as many options as possible, you'll need a list of the best cheats. **How many cheats would save you at least 100 picoseconds?**
139+
140+
---
141+
142+
## --- Part Two ---
143+
144+
The programs seem perplexed by your list of cheats. Apparently, the two-picosecond cheating rule was deprecated several milliseconds ago! The latest version of the cheating rule permits a single cheat that instead lasts at most **20 picoseconds**.
145+
146+
Now, in addition to all the cheats that were possible in just two picoseconds, many more cheats are possible. This six-picosecond cheat saves **76 picoseconds**:
147+
148+
```
149+
###############
150+
#...#...#.....#
151+
#.#.#.#.#.###.#
152+
#S#...#.#.#...#
153+
#1#####.#.#.###
154+
#2#####.#.#...#
155+
#3#####.#.###.#
156+
#456.E#...#...#
157+
###.#######.###
158+
#...###...#...#
159+
#.#####.#.###.#
160+
#.#...#.#.#...#
161+
#.#.#.#.#.#.###
162+
#...#...#...###
163+
###############
164+
```
165+
166+
Because this cheat has the same start and end positions as the one above, it's the **same cheat**, even though the path taken during the cheat is different:
167+
168+
```
169+
###############
170+
#...#...#.....#
171+
#.#.#.#.#.###.#
172+
#S12..#.#.#...#
173+
###3###.#.#.###
174+
###4###.#.#...#
175+
###5###.#.###.#
176+
###6.E#...#...#
177+
###.#######.###
178+
#...###...#...#
179+
#.#####.#.###.#
180+
#.#...#.#.#...#
181+
#.#.#.#.#.#.###
182+
#...#...#...###
183+
###############
184+
```
185+
186+
Cheats don't need to use all 20 picoseconds; cheats can last any amount of time up to and including 20 picoseconds (but can still only end when the program is on normal track). Any cheat time not used is lost; it can't be saved for another cheat later.
187+
188+
You'll still need a list of the best cheats, but now there are even more to choose between. Here are the quantities of cheats in this example that save **50 picoseconds or more**:
189+
190+
- There are 32 cheats that save 50 picoseconds.
191+
- There are 31 cheats that save 52 picoseconds.
192+
- There are 29 cheats that save 54 picoseconds.
193+
- There are 39 cheats that save 56 picoseconds.
194+
- There are 25 cheats that save 58 picoseconds.
195+
- There are 23 cheats that save 60 picoseconds.
196+
- There are 20 cheats that save 62 picoseconds.
197+
- There are 19 cheats that save 64 picoseconds.
198+
- There are 12 cheats that save 66 picoseconds.
199+
- There are 14 cheats that save 68 picoseconds.
200+
- There are 12 cheats that save 70 picoseconds.
201+
- There are 22 cheats that save 72 picoseconds.
202+
- There are 4 cheats that save 74 picoseconds.
203+
- There are 3 cheats that save 76 picoseconds.
204+
205+
Find the best cheats using the updated cheating rules. **How many cheats would save you at least 100 picoseconds?**

2024/Day_20/part_1.js

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,52 @@ const __dirname = path.dirname(fileURLToPath(import.meta.url));
88
// = Copyright (c) NullDev = //
99
// ========================= //
1010

11+
/* eslint-disable one-var, consistent-return */
12+
1113
const INPUT = String(fs.readFileSync(path.join(__dirname, "input.txt"))).trim().split("\n");
1214

1315
const pStart = performance.now();
1416

15-
//
16-
// YOUR CODE HERE
17-
//
18-
const result = "...";
17+
const map = INPUT.map(i => i.split(""));
18+
let start, end;
19+
out: for (let y = 0; y < INPUT.length; y++){
20+
for (let x = 0; x < INPUT[0].length; x++){
21+
if (map[y][x] === "S") (start = { x, y }) && (map[y][x] = ".");
22+
else if (map[y][x] === "E") (end = { x, y }) && (map[y][x] = ".");
23+
if (start && end) break out;
24+
}
25+
}
26+
27+
const res = ((
28+
p, cLen,
29+
d = (p1, p2) => Math.abs(p1.x - p2.x) + Math.abs(p1.y - p2.y), // @ts-ignore
30+
) => p.flatMap((pp1, p1) => p.slice(p1 + 1).map((pp2, i) => ({
31+
p1, p2: p1 + i + 1, pp1, pp2,
32+
dist: d(pp1, pp2),
33+
cDist: (p1 + i + 1) - p1 - d(pp1, pp2) }),
34+
).filter(({ dist, cDist }) => dist >= 2 && dist <= cLen && cDist > 0) // @ts-ignore
35+
.map(({ p1_, p2, pp1_, pp2, cDist }) => ({ p1_, p2, pp1_, pp2, saved: cDist }))))(
36+
((
37+
s, e,
38+
open = [{ ...s, pt: [s] }],
39+
closed = [],
40+
eq = (p1, p2) => p1.x === p2.x && p1.y === p2.y,
41+
) => {
42+
while (open.length){
43+
const curr = open.shift();
44+
closed.push(curr);
45+
if (eq(curr, e)) return curr;
46+
const nx = [
47+
{ x: 1, y: 0 }, { x: -1, y: 0 }, { x: 0, y: -1 }, { x: 0, y: 1 },
48+
].map(n => ({ x: (curr?.x || 0) + n.x, y: (curr?.y || 0) + n.y }))
49+
.filter(n => map[n.y]?.[n.x] === ".")
50+
.filter(n => !closed.some((c) => eq(c, n)));
51+
for (const n of nx) open.unshift({ ...n, pt: [...curr?.pt || [], n] });
52+
}
53+
})(start, end)?.pt, 2).filter((x) => x.saved >= 100,
54+
).length;
1955

2056
const pEnd = performance.now();
2157

22-
console.log("<DESCRIPTION>: " + result);
58+
console.log("CHEATS THAT SAVE AT LEAST 100pS (2): " + res);
2359
console.log(pEnd - pStart);

0 commit comments

Comments
 (0)