Skip to content

Commit edebb0c

Browse files
committed
feat(day03): Part 1
1 parent 1795df8 commit edebb0c

File tree

2 files changed

+276
-0
lines changed

2 files changed

+276
-0
lines changed

day03_test.ts

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import { assertEquals } from "https://deno.land/std@0.208.0/assert/assert_equals.ts";
2+
import { sum } from "./util/sum.ts";
3+
4+
/**
5+
* Here is an example engine schematic:
6+
*/
7+
const schematics = [
8+
`467..114..`,
9+
`...*......`,
10+
`..35..633.`,
11+
`......#...`,
12+
`617*......`,
13+
`.....+.58.`,
14+
`..592.....`,
15+
`......755.`,
16+
`...$.*....`,
17+
`.664.598.1`,
18+
];
19+
20+
Deno.test("Day 3: Gear Ratios", async (t) => {
21+
await t.step("Example", async (t) => {
22+
await t.step(
23+
"findPartNumbers()",
24+
() =>
25+
assertEquals(findPartNumbers(schematics), [
26+
{ n: 467, s: ["*"] },
27+
{ n: 114, s: [] },
28+
{ n: 35, s: ["*"] },
29+
{ n: 633, s: ["#"] },
30+
{ n: 617, s: ["*"] },
31+
{ n: 58, s: [] },
32+
{ n: 592, s: ["+"] },
33+
{ n: 755, s: ["*"] },
34+
{ n: 664, s: ["$"] },
35+
{ n: 598, s: ["*"] },
36+
{ n: 1, s: [] },
37+
]),
38+
);
39+
40+
await t.step(`Calculate the example solution`, () =>
41+
assertEquals(
42+
sum(
43+
findPartNumbers(schematics)
44+
.filter(({ s }) => s.length > 0)
45+
.map(({ n }) => n),
46+
),
47+
4361,
48+
));
49+
});
50+
51+
await t.step("Solution", async () => {
52+
const numbers = findPartNumbers(
53+
(await Deno.readTextFile("./input/day03.txt")).split("\n"),
54+
);
55+
assertEquals(
56+
sum(
57+
numbers.filter(({ s }) => s.length > 0)
58+
.map(({ n }) => n),
59+
),
60+
529618,
61+
);
62+
});
63+
});
64+
65+
/**
66+
* Find the part numbers in the schematics and the adjacent symbol(s)
67+
*/
68+
const findPartNumbers = (
69+
schematics: string[],
70+
): { n: number; s: string[] }[] => {
71+
const numbers: { n: number; s: string[] }[] = [];
72+
let currentNumber: string[] = [];
73+
let adjacentSymbols: string[] = [];
74+
75+
// Add parsed number with symbols to stash
76+
const addNumber = () => {
77+
if (currentNumber.length > 0) {
78+
numbers.push({
79+
n: parseInt(currentNumber.join("")),
80+
s: [...new Set(adjacentSymbols)],
81+
});
82+
}
83+
currentNumber = [];
84+
adjacentSymbols = [];
85+
};
86+
87+
for (let row = 0; row < schematics.length; row++) {
88+
for (let col = 0; col < schematics[row].length; col++) {
89+
const c = schematics[row][col];
90+
if (/\d/.test(c)) { // Current symbol is a number
91+
currentNumber.push(c);
92+
const s = findAdjacentSymbols(schematics, row, col);
93+
if (s !== undefined) adjacentSymbols.push(...s);
94+
} else {
95+
addNumber();
96+
}
97+
}
98+
}
99+
addNumber();
100+
return numbers;
101+
};
102+
103+
/**
104+
* Find adjacent symbols for a given field
105+
*/
106+
const findAdjacentSymbols = (
107+
schematics: string[],
108+
row: number,
109+
col: number,
110+
): string[] =>
111+
[
112+
findSymbolAt(schematics, row, col - 1), // left
113+
findSymbolAt(schematics, row - 1, col - 1), // top left
114+
findSymbolAt(schematics, row - 1, col), // top
115+
findSymbolAt(schematics, row - 1, col + 1), // top right
116+
findSymbolAt(schematics, row, col + 1), // right
117+
findSymbolAt(schematics, row + 1, col + 1), // bottom right
118+
findSymbolAt(schematics, row + 1, col), // bottom
119+
findSymbolAt(schematics, row + 1, col - 1), // bottom left
120+
].filter((s) => s !== undefined) as string[];
121+
122+
/**
123+
* Return the symbol at a given position
124+
*/
125+
const findSymbolAt = (
126+
schematics: string[],
127+
row: number,
128+
col: number,
129+
): string | undefined => {
130+
if (col < 0) return undefined; // Outside of schematics
131+
if (row < 0) return undefined; // Outside of schematics
132+
const c = schematics[row]?.[col];
133+
if (/\d/.test(c)) return undefined; // a number
134+
if (c === ".") return undefined; // a dot, ignore
135+
return c;
136+
};

0 commit comments

Comments
 (0)