advent-of-code/2023/python/day05.py
2023-12-08 13:42:42 -05:00

115 lines
2.7 KiB
Python

import shared
from pprint import pprint
from dataclasses import dataclass
@dataclass
class Mapping:
dst: int
src: int
ran: int # RANGE
maps_parts = [
"seed-to-soil",
"soil-to-fertilizer",
"fertilizer-to-water",
"water-to-light",
"light-to-temperature",
"temperature-to-humidity",
"humidity-to-location",
]
group = lambda l, s: list(zip(*(iter(l),) * s))
def line_ints(s):
return [int(x) for x in s.split() if s]
def parse_line(line):
return Mapping(*line)
class Mapper:
def __init__(self, rows):
self.parse(rows)
def parse(self, rows):
seeds = rows.pop(0)
rows.pop(0) # Discard empty to start at a clean slate
seeds = line_ints(seeds.split(":")[1])
maps = {}
current_map = None
for row in rows:
if ":" in row:
current_map = row[:-5]
maps[current_map] = []
continue
if row == "":
continue
maps[current_map].append(parse_line(line_ints(row)))
self.seeds = seeds
self.maps = maps
def calculate(self, step, source):
possibilities = self.maps[step]
for p in possibilities:
if source < p.src:
# print(f"\t{source} less than {p.src}")
continue
if source > p.src + p.ran:
# print(f"\t{source} greater than {p.src}+{p.ran}={p.src+p.ran}")
continue
# print(f"\t{source} in range")
# print(f"\t{source} is {p.dst + (source - p.src)}")
return p.dst + (source - p.src)
break
return source
# @shared.profile
def part1(rows):
mapper = Mapper(rows[:])
locations = []
for seed in mapper.seeds:
next = seed
for part in maps_parts:
_part = next
next = mapper.calculate(part, next)
locations.append(next)
print(locations)
print(min(locations))
# @shared.profile
def part2(rows):
mapper = Mapper(rows[:])
locations = []
seeds = group(mapper.seeds, 2)
for seed_group in seeds:
for seed in range(seed_group[0], seed_group[0] + seed_group[1]):
next = seed
for part in maps_parts:
_part = next
next = mapper.calculate(part, next)
locations.append(next)
print(min(locations))
def main():
rows = [row for row in shared.load_rows(5)]
with shared.elapsed_timer() as elapsed:
part1(rows)
print("🕒", elapsed())
with shared.elapsed_timer() as elapsed:
part2(rows)
print("🕒", elapsed())
if __name__ == "__main__":
main()