aoc2023/day05.py

98 lines
3.0 KiB
Python

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)