from tools.aoc import AOCDay from typing import Any def lookup(the_map: dict, source: int) -> int: for k, v in the_map.items(): if k <= source < k + v['length']: return source - k + v['dest'] return source class Day(AOCDay): inputs = [ [ (35, "input5_test"), (346433842, "input5"), ], [ (46, "input5_test"), (60294664, "input5"), ] ] def __init__(self, year: int, day: int): super().__init__(year, day) self.seed_locations = {} def get_seed_location(self, seed: int) -> int: soil = lookup(self.seed2soil, seed) fertilizer = lookup(self.soil2fertilizer, soil) water = lookup(self.fertilizer2water, fertilizer) light = lookup(self.water2light, water) temperature = lookup(self.light2temperature, light) humidity = lookup(self.temperature2humidity, temperature) location = lookup(self.humidity2location, humidity) return location def parse_input(self, part2: bool = False) -> list: seeds = [] self.seed2soil = {} self.soil2fertilizer = {} self.fertilizer2water = {} self.water2light = {} self.light2temperature = {} self.temperature2humidity = {} self.humidity2location = {} the_map = None for line in self.getInput(): if not line: continue elif line.startswith('seeds:'): _, s = line.split(": ") seeds = list(map(int, s.split())) elif line.startswith('seed-to-soil'): the_map = self.seed2soil elif line.startswith('soil-to-fertilizer'): the_map = self.soil2fertilizer elif line.startswith('fertilizer-to-water'): the_map = self.fertilizer2water elif line.startswith('water-to-light'): the_map = self.water2light elif line.startswith('light-to-temperature'): the_map = self.light2temperature elif line.startswith('temperature-to-humidity'): the_map = self.temperature2humidity elif line.startswith('humidity-to-location'): the_map = self.humidity2location else: dest, source, length = map(int, line.split()) the_map[source] = {'dest': dest, 'length': length} if part2: self.seed_locations = {} return seeds def part1(self) -> Any: seeds = self.parse_input() return min(self.get_seed_location(s) for s in seeds) def part2(self) -> Any: seeds = self.parse_input() min_loc = 2**32 for i in range(0, len(seeds), 2): for s in range(seeds[i], seeds[i] + seeds[i+1]): x = self.get_seed_location(s) if x < min_loc: min_loc = x print(i, "=>", min_loc) return min_loc if __name__ == '__main__': day = Day(2023, 5) day.run(verbose=True)