| import { readFileSync } from "fs"; |
| |
| const input = readFileSync('day 5/input.txt').toString().split('\n\n') |
| |
| interface MappedRange { |
| startRange: [number, number]; |
| offset: number; |
| } |
| |
| interface Input { |
| sts: MappedRange[]; |
| stf: MappedRange[]; |
| ftw: MappedRange[]; |
| wtl: MappedRange[]; |
| ltt: MappedRange[]; |
| tth: MappedRange[]; |
| htl: MappedRange[]; |
| } |
| |
| |
| function pointerMap(array: number[][]): MappedRange[] { |
| return array.map(arr => { |
| const startRange: [number, number] = [arr[1], arr[1] + arr[2]]; |
| const offset = arr[0] - arr[1]; |
| console.log(`Made descriptor (start -> dest): ${arr[1]} -> ${arr[0]} ... ${arr[1] + offset} -> ${arr[0] + offset}`) |
| return { |
| startRange, |
| offset |
| } |
| }) |
| } |
| |
| function findSmallestLocation(seeds: number[], mappedInput: Input): { |
| seed: number; |
| location: number; |
| } { |
| const locations: {seed: number, location: number}[] = []; |
| for(const seed of seeds) { |
| console.log(`Checking seed ${seed}`) |
| |
| let s = mappedInput.sts.find(o => o.startRange[0] <= seed && seed <= o.startRange[1]) |
| const soil = (s ? s.offset + seed : null) ?? seed |
| console.log(soil === seed ? `Continuing with default` : `Found ${soil}`) |
| |
| let f = mappedInput.stf.find(o => o.startRange[0] <= soil && soil <= o.startRange[1]) |
| const fertilizer = (f ? f.offset + soil : null) ?? soil |
| console.log(fertilizer === soil ? `Continuing with default` : `Found ${fertilizer}`) |
| |
| let w = mappedInput.ftw.find(o => o.startRange[0] <= fertilizer && fertilizer <= o.startRange[1]) |
| const water = (w ? w.offset + fertilizer : null) ?? fertilizer |
| console.log(water === fertilizer ? `Continuing with default` : `Found ${water}`) |
| |
| let li = mappedInput.wtl.find(o => o.startRange[0] <= water && water <= o.startRange[1]) |
| const light = (li ? li.offset + water : null) ?? water |
| console.log(light === water ? `Continuing with default` : `Found ${light}`) |
| |
| let t = mappedInput.ltt.find(o => o.startRange[0] <= light && light <= o.startRange[1]) |
| const temperature = (t ? t.offset + light : null) ?? light |
| console.log(temperature === light ? `Continuing with default` : `Found ${temperature}`) |
| |
| let h = mappedInput.tth.find(o => o.startRange[0] <= temperature && temperature <= o.startRange[1]) |
| const humidity = (h ? h.offset + temperature : null) ?? temperature |
| console.log(humidity === temperature ? `Continuing with default` : `Found ${humidity}`) |
| |
| let lo = mappedInput.htl.find(o => o.startRange[0] <= humidity && humidity <= o.startRange[1]) |
| const location = (lo ? lo.offset + humidity : null) ?? humidity |
| console.log(location === humidity ? `Continuing with default` : `Found ${location}`) |
| |
| locations.push({seed, location}) |
| } |
| |
| const sorted = locations.sort((a,b) => a.location < b.location ? -1 : 1); |
| return sorted[0] |
| } |
| |
| const mappedInput: Input = { |
| sts: pointerMap(input[1].split(':')[1].trim().split('\n').map(i => i.split(' ').map(n => parseInt(n)))), |
| stf: pointerMap(input[2].split(':')[1].trim().split('\n').map(i => i.split(' ').map(n => parseInt(n)))), |
| ftw: pointerMap(input[3].split(':')[1].trim().split('\n').map(i => i.split(' ').map(n => parseInt(n)))), |
| wtl: pointerMap(input[4].split(':')[1].trim().split('\n').map(i => i.split(' ').map(n => parseInt(n)))), |
| ltt: pointerMap(input[5].split(':')[1].trim().split('\n').map(i => i.split(' ').map(n => parseInt(n)))), |
| tth: pointerMap(input[6].split(':')[1].trim().split('\n').map(i => i.split(' ').map(n => parseInt(n)))), |
| htl: pointerMap(input[7].split(':')[1].trim().split('\n').map(i => i.split(' ').map(n => parseInt(n)))) |
| }; |
| console.log(`Generating descriptors for seed to soil`); |
| console.log(`Generating descriptors for soil to fertilizer`); |
| console.log(`Generating descriptors for fertilizer to water`); |
| console.log(`Generating descriptors for water to light`); |
| console.log(`Generating descriptors for light to temp`); |
| console.log(`Generating descriptors for temp to humidity`); |
| console.log(`Generating descriptors for humidity to location`); |
| |
| |
| // Part 1 |
| ;(() => { |
| const seeds = input[0].split(':')[1].trim().split(' ').map(i => parseInt(i)); |
| const smallest = findSmallestLocation(seeds, mappedInput) |
| |
| console.log(`(Part 1) Lowest location number: (seed: ${smallest.seed}) ${smallest.location}`) |
| })(); |
| |
| |
| // Part 2 |
| |
| function findSmallestLocationRange(seeds: number[], mappedInput: Input): { |
| seed: number; |
| location: number; |
| } { |
| const locations: {seed: number, location: number}[] = []; |
| for(const seed of seeds) { |
| |
| console.log(`Checking seed ${seed}`) |
| |
| let s = mappedInput.sts.find(o => o.startRange[0] <= seed && seed <= o.startRange[1]) |
| const soil = (s ? s.offset + seed : null) ?? seed |
| console.log(soil === seed ? `Continuing with default` : `Found ${soil}`) |
| |
| let f = mappedInput.stf.find(o => o.startRange[0] <= soil && soil <= o.startRange[1]) |
| const fertilizer = (f ? f.offset + soil : null) ?? soil |
| console.log(fertilizer === soil ? `Continuing with default` : `Found ${fertilizer}`) |
| |
| let w = mappedInput.ftw.find(o => o.startRange[0] <= fertilizer && fertilizer <= o.startRange[1]) |
| const water = (w ? w.offset + fertilizer : null) ?? fertilizer |
| console.log(water === fertilizer ? `Continuing with default` : `Found ${water}`) |
| |
| let li = mappedInput.wtl.find(o => o.startRange[0] <= water && water <= o.startRange[1]) |
| const light = (li ? li.offset + water : null) ?? water |
| console.log(light === water ? `Continuing with default` : `Found ${light}`) |
| |
| let t = mappedInput.ltt.find(o => o.startRange[0] <= light && light <= o.startRange[1]) |
| const temperature = (t ? t.offset + light : null) ?? light |
| console.log(temperature === light ? `Continuing with default` : `Found ${temperature}`) |
| |
| let h = mappedInput.tth.find(o => o.startRange[0] <= temperature && temperature <= o.startRange[1]) |
| const humidity = (h ? h.offset + temperature : null) ?? temperature |
| console.log(humidity === temperature ? `Continuing with default` : `Found ${humidity}`) |
| |
| let lo = mappedInput.htl.find(o => o.startRange[0] <= humidity && humidity <= o.startRange[1]) |
| const location = (lo ? lo.offset + humidity : null) ?? humidity |
| console.log(location === humidity ? `Continuing with default` : `Found ${location}`) |
| |
| locations.push({seed, location}) |
| } |
| |
| const sorted = locations.sort((a,b) => a.location < b.location ? -1 : 1); |
| return sorted[0] |
| } |
| |
| |
| |
| ;(() => { |
| const unformattedSeeds = input[0].split(':')[1].trim().match(/(\d+ \d+)/g)?.map(i => i.split(' ').map(n => parseInt(n.trim()))) |
| const seeds: number[] = []; |
| |
| if(!unformattedSeeds) throw new Error('How did this happen') |
| |
| for(const US of unformattedSeeds) { |
| for(let i = 0; i < US[1]; i++) { |
| seeds.push(US[0] + i); |
| } |
| } |
| |
| const smallest = findSmallestLocation(seeds, mappedInput) |
| |
| console.log(`(Part 2) Lowest location number: (seed: ${smallest.seed}) ${smallest.location}`) |
| })(); |