Skip to content

Commit 7f3a7b8

Browse files
committed
feat: 2024 Day 18
1 parent 562f220 commit 7f3a7b8

File tree

4 files changed

+146
-0
lines changed

4 files changed

+146
-0
lines changed

2024/day/18/part/1/solve.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import solve from "./solve.ts";
2+
3+
import { assertEquals } from "@std/assert";
4+
5+
Deno.test("example", () => {
6+
const input = `\
7+
5,4
8+
4,2
9+
4,5
10+
3,0
11+
2,1
12+
6,3
13+
2,4
14+
1,5
15+
0,6
16+
3,3
17+
2,6
18+
5,1
19+
1,2
20+
5,5
21+
2,5
22+
6,5
23+
1,4
24+
0,4
25+
6,4
26+
1,1
27+
6,1
28+
1,0
29+
0,5
30+
1,6
31+
2,0`;
32+
33+
assertEquals(solve(input, { size: 7, bytes: 12 }), 22);
34+
});

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
const directions = [[0, -1], [0, 1], [-1, 0], [1, 0]];
2+
3+
function findLeastTimeToExit(
4+
locations: readonly number[][],
5+
size: number,
6+
bytes: number,
7+
) {
8+
const grid = Array.from(
9+
{ length: size },
10+
() => Array.from({ length: size }),
11+
);
12+
for (let byte = 0; byte < bytes; byte++) {
13+
const [x, y] = locations[byte];
14+
grid[y][x] = "#";
15+
}
16+
const xf = size - 1, yf = xf;
17+
const queue = [[0, 0, 0]];
18+
const seen = new Set<`${number},${number}`>();
19+
while (queue.length) {
20+
const [x, y, t] = queue.shift()!;
21+
if (!(y in grid) || !(x in grid[y]) || grid[y][x] === "#") continue;
22+
if (x === xf && y === yf) return t;
23+
const hash = `${x},${y}` as const;
24+
if (seen.has(hash)) continue;
25+
seen.add(hash);
26+
for (const [dx, dy] of directions) queue.push([x + dx, y + dy, t + 1]);
27+
}
28+
}
29+
30+
export default function solve(input: string, { size = 71, bytes = 1024 } = {}) {
31+
const locations = input.split("\n")
32+
.map((line) => line.split(",").map(Number));
33+
return findLeastTimeToExit(locations, size, bytes);
34+
}

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import solve from "./solve.ts";
2+
3+
import { assertEquals } from "@std/assert";
4+
5+
Deno.test("example", () => {
6+
const input = `\
7+
5,4
8+
4,2
9+
4,5
10+
3,0
11+
2,1
12+
6,3
13+
2,4
14+
1,5
15+
0,6
16+
3,3
17+
2,6
18+
5,1
19+
1,2
20+
5,5
21+
2,5
22+
6,5
23+
1,4
24+
0,4
25+
6,4
26+
1,1
27+
6,1
28+
1,0
29+
0,5
30+
1,6
31+
2,0`;
32+
33+
assertEquals(solve(input, { size: 7 }), "6,1");
34+
});

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

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const directions = [[0, -1], [0, 1], [-1, 0], [1, 0]];
2+
3+
function findLeastTimeToExit(
4+
locations: readonly number[][],
5+
size: number,
6+
bytes: number,
7+
) {
8+
const grid = Array.from(
9+
{ length: size },
10+
() => Array.from({ length: size }),
11+
);
12+
for (let byte = 0; byte < bytes; byte++) {
13+
const [x, y] = locations[byte];
14+
grid[y][x] = "#";
15+
}
16+
const xf = size - 1, yf = xf;
17+
const queue = [[0, 0, 0]];
18+
const seen = new Set<`${number},${number}`>();
19+
while (queue.length) {
20+
const [x, y, t] = queue.shift()!;
21+
if (!(y in grid) || !(x in grid[y]) || grid[y][x] === "#") continue;
22+
if (x === xf && y === yf) return t;
23+
const hash = `${x},${y}` as const;
24+
if (seen.has(hash)) continue;
25+
seen.add(hash);
26+
for (const [dx, dy] of directions) queue.push([x + dx, y + dy, t + 1]);
27+
}
28+
}
29+
30+
export default function solve(input: string, { size = 71 } = {}) {
31+
const locations = input.split("\n")
32+
.map((line) => line.split(",").map(Number));
33+
let low = 0, high = locations.length - 1;
34+
while (low <= high) {
35+
const mid = Math.floor((low + high) / 2);
36+
const t = findLeastTimeToExit(locations, size, mid);
37+
if (t === undefined) {
38+
high = mid - 1;
39+
} else {
40+
low = mid + 1;
41+
}
42+
}
43+
return locations[high].join(",");
44+
}

0 commit comments

Comments
 (0)