advent of code 2025 in ts and nix
1const file = await Bun.file("../../shared/04/input.txt").text();
2const paperMap: boolean[][] = file
3 .trim()
4 .split("\n")
5 .map((line) =>
6 Array.from(line, (ch) => {
7 if (ch === ".") return false;
8 if (ch === "@") return true;
9
10 throw new Error(`Unexpected character '${ch}' in input.`);
11 }),
12 );
13
14function accessiblePapers(map: boolean[][]): {
15 map: boolean[][];
16 accessible: number;
17} {
18 let accessible = 0;
19 const nextMap: boolean[][] = map.map((row) => row.slice());
20 map.forEach((rows, row) => {
21 rows.forEach((cell, col) => {
22 if (cell) {
23 let fullAdj = 0;
24
25 const offsets: { row: number; col: number }[] = [
26 // cardinal
27 { row: -1, col: 0 },
28 { row: 1, col: 0 },
29 { row: 0, col: 1 },
30 { row: 0, col: -1 },
31 // diagonals
32 { row: -1, col: 1 },
33 { row: 1, col: 1 },
34 { row: -1, col: -1 },
35 { row: 1, col: -1 },
36 ];
37
38 for (const off of offsets) {
39 const rowIdx = row + off.row;
40 const colIdx = col + off.col;
41
42 if (rowIdx < 0 || colIdx < 0) continue;
43 if (rowIdx > paperMap.length - 1 || colIdx > rows.length - 1)
44 continue;
45
46 if (map.at(rowIdx)?.at(colIdx)) fullAdj++;
47
48 if (fullAdj >= 4) break;
49 }
50
51 if (fullAdj < 4) {
52 accessible++;
53 (nextMap[row] as boolean[])[col] = false;
54 }
55 }
56 });
57 });
58
59 return { map: nextMap, accessible };
60}
61
62(() => {
63 // Part 1
64 console.log("part 1:", accessiblePapers(paperMap).accessible);
65})();
66
67(() => {
68 let totalAcessible = 0;
69 let map = paperMap;
70 while (true) {
71 const res = accessiblePapers(map);
72
73 totalAcessible += res.accessible;
74 map = res.map;
75
76 if (res.accessible === 0) break;
77 }
78
79 // Part 2
80 console.log("part 2:", totalAcessible);
81})();