from __future__ import annotations from dataclasses import dataclass from itertools import chain import regex as re from aoc import Aoc2, AocSameParser @dataclass class Map: source: str dest: str start_source: int start_dest: int id_range: int @staticmethod def from_group(group: list[str]) -> list[Map]: header_match = re.match(r"(?P[^-]*)-to-(?P[^ ]*) map:", group[0]) if header_match is None: raise RuntimeError(f'Could not parse "{group[0]}" as group header') source = header_match["source"] dest = header_match["dest"] maps = [] for line in group[1:]: start_source, start_dest, id_range = [ int(d) for d in re.findall(r"\d+", line) ] maps.append(Map(source, dest, start_source, start_dest, id_range)) return maps @dataclass class Problem: seeds: list[int] maps: list[Map] @staticmethod def from_input(inpt: str) -> Problem: lines = inpt.splitlines() seed_match = re.match(r"seeds:(\s*(?P\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 = list(chain.from_iterable(Map.from_group(group) 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) -> None: print(inpt) def part2(self, inpt: Problem) -> None: pass def main(): day5 = Day05() day5.run_example_1() if __name__ == "__main__": main()