import re from dataclasses import dataclass from typing import Optional, Dict, List, Tuple @dataclass class AlmanacMap: destination: int source: int length: int def is_mapped(self, source: int) -> bool: return self.source <= source < self.source + self.length def mapped_value(self, source: int) -> Optional[int]: if not self.is_mapped(source): return None return self.destination + (source - self.source) def extract(input_file: str) -> Tuple[List[int], Dict[str, List[AlmanacMap]]]: seeds = [] maps = { "seed-to-soil": [], "soil-to-fertilizer": [], "fertilizer-to-water": [], "water-to-light": [], "light-to-temperature": [], "temperature-to-humidity": [], "humidity-to-location": [], } with open(input_file) as input: current_map = {} while line := input.readline(): if match := re.match("seeds: (.*)", line): for seed in match.group(1).split(" "): seeds.append(int(seed)) continue if match := re.match("([a-z-]+) map:", line): current_map = maps[match.group(1)] continue if match := re.match("([\d ]+)", line): destination, source, length = match.group(1).split(" ") current_map.append(AlmanacMap(destination=int(destination), source=int(source), length=int(length))) return seeds, maps