advent-of-code-2023/src/day_three.ts

90 lines
3.5 KiB
TypeScript
Raw Normal View History

import { takeWhile } from 'lodash';
import fs from "fs";
2023-12-03 12:17:08 +00:00
import {matchAllAndThen} from "./utils";
export class Engine {
2023-12-03 12:17:08 +00:00
constructor(private readonly parts: number[][], private readonly schematic: string[][]) {
}
2023-12-03 12:17:08 +00:00
public static create(input: string, gearsOnly: boolean = false): Engine {
const lines = input.split('\n').filter(Boolean);
const partRegex = /\d+/g;
2023-12-03 12:17:08 +00:00
const symbolRegex = gearsOnly ? /\*/g : /[^a-zA-Z\d\.]/g;
const parts : number[][] = new Array(lines.length).fill(0).map(() => new Array(lines[0].length));
const symbols: string[][] = new Array(lines.length).fill(0).map(() => new Array(lines[0].length));
lines.forEach((line, lineNumber) => {
2023-12-03 12:17:08 +00:00
matchAllAndThen(line, partRegex, (match, index) => {
const parsedNumber = parseInt(match, 10);
for (let i = index; i < index + match.length; i++) {
parts[lineNumber][i] = parsedNumber;
}
});
});
lines.forEach((line, lineNumber) => {
2023-12-03 12:17:08 +00:00
matchAllAndThen(line, symbolRegex, (match, index) => symbols[lineNumber][index] = match);
});
2023-12-03 12:17:08 +00:00
return new Engine(parts, symbols);
}
public sumPartNumbers(): number {
const partsList = this.schematic.flatMap((row, rowIndex) =>
row.map((symbol, index) => {
2023-12-03 12:17:08 +00:00
if (!symbol) return symbol;
2023-12-03 12:17:08 +00:00
const partIndex = [
[rowIndex - 1, index - 1],
[rowIndex - 1, index],
[rowIndex - 1, index + 1],
[rowIndex, index - 1],
[rowIndex, index + 1],
[rowIndex + 1, index - 1],
[rowIndex + 1, index],
[rowIndex + 1, index + 1]
];
return Array.from(new Set(partIndex.filter(([rowNum, col]) => rowNum >= 0 && rowNum <= this.schematic.length && index >= 0 && index <= row.length)
.map(([rowNum, column]) => {
return this.parts[rowNum][column]
}).filter(Boolean)))
.reduce((total, val) => total + val,0);
})
2023-12-03 12:17:08 +00:00
) as number[];
return partsList.reduce((total, partNumber) => total + partNumber, 0);
}
2023-12-03 12:17:08 +00:00
public gearRatioSums(): number {
return this.schematic.flatMap((row, rowIndex) =>
row
.map((symbol, index) => {
const partIndex = [
[rowIndex - 1, index - 1],
[rowIndex - 1, index],
[rowIndex - 1, index + 1],
[rowIndex, index - 1],
[rowIndex, index + 1],
[rowIndex + 1, index - 1],
[rowIndex + 1, index],
[rowIndex + 1, index + 1]
];
return Array.from(new Set(partIndex.filter(([rowNum, col]) => rowNum >= 0 && rowNum <= this.schematic.length && index >= 0 && index <= row.length)
.map(([rowNum, column]) => {
return this.parts[rowNum][column]
}).filter(Boolean)))
})
).filter(list => list.length === 2)
.reduce((total, [a, b]) => {
return total + (a * b)
}, 0);
}
}
export const runDayThree = () => {
const input = fs.readFileSync('./inputs/day_three_input.txt', 'utf8');
2023-12-03 12:17:08 +00:00
console.log(Engine.create(input).sumPartNumbers())
console.log(Engine.create(input, true).gearRatioSums())
}