import { Coll, Collection, Collection2D } from "util/collection";
type MapFormat = {
destStart: number;
sourceStart: number;
length: number;
};
function fillColl(iter: Iterable<string>): Collection<MapFormat> {
const result = Coll<MapFormat>();
for (const opts of iter) {
if (opts === "") {
break;
}
const [destStart, sourceStart, length] = opts.split(" ", 3).map(
Number,
);
result.push({
destStart,
sourceStart,
length,
});
}
return result;
}
type MappedInputs = [seeds: Collection<number>, maps: Collection2D<MapFormat>];
// If blank strings/ints is not enough
export const inputMapper = (
inputs: Collection<string>,
): MappedInputs => {
const result: Collection2D<MapFormat> = Coll();
const [_, seedStr] = inputs[0].split(": ", 2);
const seeds = Coll(...seedStr.split(" ").map(Number));
const iter = inputs.iter();
for (const row of iter) {
if (row.startsWith("seed-to-soil")) {
result.push(fillColl(iter));
continue;
}
if (row.startsWith("soil-to-fertilizer")) {
result.push(fillColl(iter));
continue;
}
if (row.startsWith("fertilizer-to-water")) {
result.push(fillColl(iter));
continue;
}
if (row.startsWith("water-to-light")) {
result.push(fillColl(iter));
continue;
}
if (row.startsWith("light-to-temperature")) {
result.push(fillColl(iter));
continue;
}
if (row.startsWith("temperature-to-humidity")) {
result.push(fillColl(iter));
continue;
}
if (row.startsWith("humidity-to-location")) {
result.push(fillColl(iter));
continue;
}
}
return [seeds, result];
};
export function solution1([seeds, maps]: MappedInputs): number {
const result = seeds.map((seed) =>
maps.reduce((prev, curr) => {
for (
const { destStart, sourceStart, length } of curr
) {
if (prev >= sourceStart && prev < sourceStart + length) {
return destStart + (prev - sourceStart);
}
}
return prev;
}, seed)
).x.min();
return result;
}
type SeedTuple = [from: number, length: number];
export function solution2([seeds, maps]: MappedInputs): number {
const multiSeed = seeds.partition(2) as unknown as Collection<
SeedTuple
>;
let result = Number.MAX_SAFE_INTEGER;
for (const [from, length] of multiSeed) {
for (let i = 0; i < length; i++) {
const currSeed = from + i;
const currResult = solution1([Coll(currSeed), maps]);
if (currResult < result) {
result = currResult;
}
}
}
return result;
}