99 lines
2.5 KiB
TypeScript
99 lines
2.5 KiB
TypeScript
const sample = await Deno.readTextFile("sample.txt");
|
|
const input = await Deno.readTextFile("input.txt");
|
|
|
|
interface Result<T> {
|
|
value: T;
|
|
line: number;
|
|
length: number;
|
|
index: number;
|
|
}
|
|
|
|
const isSymbol = (char: string): boolean =>
|
|
char !== undefined && isNaN(parseFloat(char)) && char !== ".";
|
|
|
|
const isGear = (char: string): boolean => char === "*";
|
|
|
|
const hasSurrounding = (
|
|
dataMap: string[],
|
|
{ line, index, length }: Result<number>,
|
|
predicate: (char: string) => boolean,
|
|
): { row: number; column: number }[] => {
|
|
const result: { row: number; column: number }[] = [];
|
|
for (let row = line - 1; row <= line + 1; row += 1) {
|
|
for (let column = index - 1; column < index + length + 1; column += 1) {
|
|
if (predicate(dataMap[row]?.[column])) result.push({ row, column });
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
|
|
const solvePart1 = (data: string): number => {
|
|
const dataMap = data
|
|
.split("\n")
|
|
.filter(Boolean);
|
|
|
|
return dataMap.map((line, index) =>
|
|
Array.from(
|
|
line.matchAll(/\d+/g),
|
|
(x): Result<number> => ({
|
|
value: parseFloat(x[0]),
|
|
line: index,
|
|
length: x[0].length,
|
|
index: x.index ?? -1,
|
|
}),
|
|
)
|
|
).flat()
|
|
.reduce(
|
|
(sum, result) =>
|
|
hasSurrounding(dataMap, result, isSymbol).length
|
|
? sum + result.value
|
|
: sum,
|
|
0,
|
|
);
|
|
};
|
|
|
|
console.log("Sample:", solvePart1(sample)); // 4361
|
|
console.log("Input", solvePart1(input)); // 550934
|
|
|
|
const solvePart2 = (data: string): number => {
|
|
const dataMap = data
|
|
.split("\n")
|
|
.filter(Boolean);
|
|
|
|
const numbersPerGear = dataMap.map((line, index) =>
|
|
Array.from(
|
|
line.matchAll(/\d+/g),
|
|
(x): Result<number> => ({
|
|
value: parseFloat(x[0]),
|
|
line: index,
|
|
length: x[0].length,
|
|
index: x.index ?? -1,
|
|
}),
|
|
)
|
|
).flat()
|
|
.map(
|
|
(result) => ({
|
|
...result,
|
|
gears: hasSurrounding(dataMap, result, isGear),
|
|
}),
|
|
).reduce((group, result): Record<string, number[]> => {
|
|
result.gears.forEach((gear) => {
|
|
group[`${gear.row}:${gear.column}`] = [
|
|
...(group[`${gear.row}:${gear.column}`] || []),
|
|
result.value,
|
|
];
|
|
});
|
|
return group;
|
|
}, {} as Record<string, number[]>);
|
|
|
|
return Object.values(numbersPerGear).reduce(
|
|
(sum, result) =>
|
|
result.length > 1 ? sum + result.reduce((s, v) => s * v) : sum,
|
|
0,
|
|
);
|
|
|
|
};
|
|
|
|
console.log("Sample2:", solvePart2(sample)); // 467835
|
|
console.log("Input", solvePart2(input)); // 81997870
|