advent_of_code_2023/Day08/ts/solution.ts

83 lines
2.9 KiB
TypeScript

import * as fs from 'fs';
import * as path from 'path';
function gcd(a: number, b: number): number {
while (b !== 0) {
const t = b;
b = a % b;
a = t;
}
return a;
}
function lcm(a: number, b: number): number {
return (a * b) / gcd(a, b);
}
function parseFile(filePath: string): { steps: number[], rules: { [key: string]: { [key: string]: string } } } {
console.log(`Parsing file: ${filePath}`);
const data = fs.readFileSync(filePath, 'utf8').trim();
const [stepsSection, rulesSection] = data.split('\n\n');
const steps = stepsSection.split('').map((char: string) => char === 'L' ? 0 : 1);
const rules = rulesSection.split('\n').reduce((acc: { [key: string]: { [key: string]: string } }, line: string) => {
const [state, directions] = line.split('=').map((s: string) => s.trim());
const [left, right] = directions.split(',').map((s: string) => s.trim());
acc['L'][state] = left.slice(1);
acc['R'][state] = right.slice(0, -1);
return acc;
}, { 'L': {}, 'R': {} });
return { steps, rules };
}
function navigateNetworkSimultaneously(steps: number[], rules: { [key: string]: { [key: string]: string } }): number {
console.log("Starting navigation of network.");
const startNodes = Object.keys(rules['L']).filter((node: string) => node.endsWith('A'));
const currentNodes = startNodes;
let stepCount = 0;
const timeToZ: { [key: number]: number } = {};
while (Object.keys(timeToZ).length < startNodes.length) {
currentNodes.forEach((node: string, index: number) => {
const direction = steps[stepCount % steps.length] === 0 ? 'L' : 'R';
const nextNode = rules[direction][node];
currentNodes[index] = nextNode;
if (nextNode.endsWith('Z') && !(index in timeToZ)) {
timeToZ[index] = stepCount + 1;
}
});
stepCount++;
console.log(`Step ${stepCount}: Current nodes - ${currentNodes}`);
}
return Object.values(timeToZ).reduce((acc: number, val: number) => lcm(acc, val), 1);
}
function runTest(): void {
console.log("Running test...");
const testPath = path.join(__dirname, '../test.txt');
const { steps, rules } = parseFile(testPath);
const expected = 6;
const result = navigateNetworkSimultaneously(steps, rules);
if (result !== expected) {
throw new Error(`Test failed: expected ${expected}, got ${result}`);
}
console.log(`Test passed with ${result} steps.`);
}
function main(): void {
try {
runTest();
const inputPath = path.join(__dirname, '../input.txt');
const { steps, rules } = parseFile(inputPath);
const result = navigateNetworkSimultaneously(steps, rules);
console.log(`All paths reached 'Z' nodes simultaneously in ${result} steps.`);
} catch (error) {
console.error(`Error: ${(error as Error).message}`);
}
}
main();