advent_of_code_2023/Day05/ts/solution.ts

108 lines
3.7 KiB
TypeScript
Raw Normal View History

2023-12-06 18:32:42 +00:00
import * as fs from 'fs';
function parseInput(filePath: string): { seedsNumbers: number[][], categories: number[][][] } {
console.log(`Parsing input from ${filePath}`);
const data: string[] = fs.readFileSync(filePath, 'utf8').trim().split('\n\n');
const firstLine = data.shift();
if (!firstLine) {
throw new Error('Input file is not in the expected format');
}
const seedsLine: string = firstLine.split(':')[1].trim();
const seedsRanges: number[] = seedsLine.split(/\s+/).map(Number);
const seedsNumbers: number[][] = [];
for (let i = 0; i < seedsRanges.length; i += 2) {
seedsNumbers.push([seedsRanges[i], seedsRanges[i] + seedsRanges[i + 1]]);
}
const categories: number[][][] = data.map(category => {
return category.split('\n').slice(1).map(line => line.split(/\s+/).map(Number));
});
console.log(`Parsed ${seedsNumbers.length} seed ranges and ${categories.length} categories`);
return { seedsNumbers, categories };
}
function processCategories(seedsNumbers: number[][], categories: number[][][]): number[][] {
console.log('Processing categories');
categories.forEach((category, index) => {
console.log(`Processing category ${index + 1}`);
const sources: number[][] = [];
2023-12-06 18:32:42 +00:00
while (seedsNumbers.length) {
const seedPair = seedsNumbers.pop();
if (!seedPair) {
throw new Error('Unexpected empty seed range');
}
const [start, end] = seedPair;
let found = false;
for (const [destination, source, length] of category) {
const overlapStart: number = Math.max(start, source);
const overlapEnd: number = Math.min(end, source + length);
if (overlapStart < overlapEnd) {
found = true;
sources.push([overlapStart - source + destination, overlapEnd - source + destination]);
if (overlapStart > start) {
seedsNumbers.push([start, overlapStart]);
}
if (end > overlapEnd) {
seedsNumbers.push([overlapEnd, end]);
}
break;
}
}
if (!found) {
sources.push([start, end]);
}
}
seedsNumbers.push(...sources);
});
console.log('Completed processing categories');
return seedsNumbers;
}
function findLowestLocation(filePath: string): number {
try {
console.log(`Finding lowest location for file: ${filePath}`);
const { seedsNumbers, categories } = parseInput(filePath);
const processedSeeds = processCategories(seedsNumbers, categories);
const lowestLocation = Math.min(...processedSeeds.flat());
console.log(`Lowest location found: ${lowestLocation}`);
return lowestLocation;
} catch (error) {
console.error(`An error occurred processing '${filePath}': ${(error as Error).message}`);
throw error;
}
}
function test() {
console.log('Starting test');
const expected = 46;
try {
const result = findLowestLocation('../test.txt');
if (result !== expected) {
throw new Error(`Test failed, expected ${expected} but got ${result}`);
}
console.log('Test passed.');
} catch (error) {
console.error(`Test error: ${(error as Error).message}`);
throw error;
}
}
function main() {
try {
test();
const result = findLowestLocation('../input.txt');
console.log(`Total result from input.txt: ${result}`);
} catch (error) {
console.error(`An error occurred in main: ${(error as Error).message}`);
}
}
main();