aoc2023/day05.py

117 lines
3.5 KiB
Python

from __future__ import annotations
from dataclasses import dataclass
from itertools import chain
import bisect
import regex as re
from aoc import Aoc2, AocSameParser
class Map:
def __init__(self, group: list[str]) -> None:
self.maps = []
for line in group[1:]:
start_dest, start_source, id_range = [
int(d) for d in re.findall(r"\d+", line)
]
bisect.insort(self.maps, (start_source, start_dest, id_range))
def __getitem__(self, x: int) -> int:
print(f"In {x}")
for (source, dest, rnge) in self.maps:
print(f"Source {source}")
if x >= source and x < source + rnge:
return dest + (x - source)
return x
# index = bisect.bisect_left(self.maps, (x+1,0,0))
# index -= 1
# if index < 0:
# return x
#
# source, dest, id_range = self.maps[index]
# if x < source + id_range:
# return dest + (x - source)
# return x
def __repr__(self) -> str:
l = []
for k, v, x in self.maps:
l.append(f"{k} - {k + x}: {v} - {v + x}")
return f"Map({', '.join(l)})"
@dataclass
class Problem:
seeds: list[int]
maps: dict[tuple[str,str],Map]
def convert(self, cat_from: str, cat_to:str, value: int) -> int:
target = cat_from
output_value = value
while target != cat_to:
new_target= list(filter(lambda fromto: fromto[0] == target, self.maps.keys()))[0][1]
print(f"{target}({output_value})")
output_value = self.maps[(target, new_target)][output_value]
print(f"{new_target}({output_value})")
target = new_target
return output_value
@staticmethod
def parse_header(line: str) -> tuple[str, str]:
header_match = re.match(r"(?P<source>[^-]*)-to-(?P<dest>[^ ]*) map:", line)
if header_match is None:
raise RuntimeError(f'Could not parse "{line}" as group header')
return header_match["source"], header_match["dest"]
@staticmethod
def from_input(inpt: str) -> Problem:
lines = inpt.splitlines()
seed_match = re.match(r"seeds:(\s*(?P<seedid>\d+)\s*)*", lines[0])
if seed_match is None:
raise RuntimeError(f'Could not parse "{lines[0]}" as seed list')
seeds = [int(s) for s in seed_match.captures("seedid")]
groups = []
for line in lines[1:]:
if not line:
groups.append([])
else:
groups[-1].append(line)
maps = {Problem.parse_header(group[0]): Map(group[1:]) for group in groups}
return Problem(seeds, maps)
class Day05(AocSameParser[Problem], Aoc2[Problem, Problem]):
def __init__(self) -> None:
Aoc2.__init__(self, 2023, 5, example_code_nr2=0)
def parseinput(self, inpt: str) -> Problem:
return Problem.from_input(inpt)
def part1(self, inpt: Problem) -> int:
return min(inpt.convert("seed", "location", x) for x in inpt.seeds)
def part2(self, inpt: Problem) -> int:
print(inpt.maps[("light", "temperature")])
print(inpt.convert("seed", "location", 82))
# seed_iter = iter(inpt.seeds)
# seeds = []
# for start, rnge in zip(seed_iter, seed_iter):
# seeds.extend(range(start,start+rnge))
# print([inpt.convert("seed", "location", x) for x in seeds])
def main():
day5 = Day05()
day5.run_example_2()
if __name__ == "__main__":
main()