Files
advent-of-code-2022/2023/05/solution.ts
2023-12-07 21:44:02 +01:00

166 lines
4.1 KiB
TypeScript

const sample = await Deno.readTextFile("sample.txt");
const input = await Deno.readTextFile("input.txt");
interface Map {
s: number;
d: number;
l: number;
}
interface ParsedInput {
seeds: number[];
seedToSoil: Map[];
soilToFertilizer: Map[];
fertilizerToWater: Map[];
waterToLight: Map[];
lightToTemperature: Map[];
temperatureToHumidity: Map[];
humidityToLocation: Map[];
}
const computeMap = (maps: Map[]) => (input: number): number => {
for (const { s, d, l } of maps) {
if (input >= s && input < s + l) return (input - s) + d;
}
return input;
};
const parseInput = (input: string): ParsedInput => {
const seeds: number[] =
input.split("\n\n").shift()?.split(" ").slice(1).map(parseFloat) || [];
const parsed = input.split("\n\n")
.filter(Boolean)
.slice(1)
.map((map): string[] => map.split(/:\ |\ map:\ *\n*/))
.map((
[name, rows],
): [string, number[][]] => [
name,
rows.trim().split(/\n/).map((values) =>
values.split(/\ /).map(parseFloat)
),
]);
let seedToSoil: Map[] = [];
let soilToFertilizer: Map[] = [];
let fertilizerToWater: Map[] = [];
let waterToLight: Map[] = [];
let lightToTemperature: Map[] = [];
let temperatureToHumidity: Map[] = [];
let humidityToLocation: Map[] = [];
parsed.forEach((
[name, mapValues],
) => {
const maps = mapValues.map(([d, s, l]) => ({ d, s, l }));
if (name === "seed-to-soil") {
seedToSoil = maps;
} else if (name === "soil-to-fertilizer") {
soilToFertilizer = maps;
} else if (name === "fertilizer-to-water") {
fertilizerToWater = maps;
} else if (name === "water-to-light") {
waterToLight = maps;
} else if (name === "light-to-temperature") {
lightToTemperature = maps;
} else if (name === "temperature-to-humidity") {
temperatureToHumidity = maps;
} else if (name === "humidity-to-location") {
humidityToLocation = maps;
}
});
return {
seeds,
seedToSoil,
soilToFertilizer,
fertilizerToWater,
waterToLight,
lightToTemperature,
temperatureToHumidity,
humidityToLocation,
};
};
const solvePart1 = (data: string): number => {
const {
seeds,
seedToSoil,
soilToFertilizer,
fertilizerToWater,
waterToLight,
lightToTemperature,
temperatureToHumidity,
humidityToLocation,
} = parseInput(data);
return seeds
.map(computeMap(seedToSoil))
.map(computeMap(soilToFertilizer))
.map(computeMap(fertilizerToWater))
.map(computeMap(waterToLight))
.map(computeMap(lightToTemperature))
.map(computeMap(temperatureToHumidity))
.map(computeMap(humidityToLocation))
.reduce((m, v) => Math.min(m, v));
};
console.log("Sample:", solvePart1(sample)); // 35
console.log("Input", solvePart1(input)); // 265018614
const getRanges = (list: number[]): [number, number][] => {
const result: [number, number][] = [];
for (let i = 0; i < list.length; i += 2) {
result.push([list[i], list[i + 1]]);
}
return result;
};
const mapRange = (s: number, l: number, fn: (n: number) => void): void => {
for (let i = s; i < s + l; i += 1) {
fn(i);
}
};
const solvePart2 = (data: string): number => {
const {
seeds: seedRanges,
seedToSoil,
soilToFertilizer,
fertilizerToWater,
waterToLight,
lightToTemperature,
temperatureToHumidity,
humidityToLocation,
} = parseInput(data);
console.log("getRanges(seedRanges)", getRanges(seedRanges));
const fn = (n: number): number =>
computeMap(humidityToLocation)(
computeMap(temperatureToHumidity)(
computeMap(lightToTemperature)(
computeMap(waterToLight)(
computeMap(fertilizerToWater)(
computeMap(soilToFertilizer)(computeMap(seedToSoil)(n)),
),
),
),
),
);
let lowest = Number.MAX_VALUE
getRanges(seedRanges).forEach(([s, l]) => {
console.log("range", s, lowest);
mapRange(s, l, (n) => {
lowest = Math.min(lowest, fn(n));
});
});
return lowest;
};
console.log("Sample:", solvePart2(sample)); // 46
console.log("Input", solvePart2(input)); // 63179500