diff --git a/day05.py b/day05.py index 6e0819e..22c1098 100644 --- a/day05.py +++ b/day05.py @@ -2,6 +2,7 @@ from __future__ import annotations from dataclasses import dataclass from itertools import chain import bisect +from typing import Optional import regex as re @@ -13,35 +14,62 @@ class Map: def __init__(self, group: list[str]) -> None: self.maps = [] - for line in group[1:]: + for line in group: 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)) + bisect.insort(self.maps, (start_source, start_dest - start_source, id_range)) + zero_offsets = [] + start = 0 + for source, _, rnge in self.maps: + if source > start: + zero_offsets.append((start, 0, source - start)) + start = source + rnge + for m in zero_offsets: + bisect.insort(self.maps, m) + + def find_bucket(self, x: int) -> Optional[int]: + for idx, (source, offset, rnge) in enumerate(self.maps): + if x >= source and x < source + rnge: + return idx + return None + def __getitem__(self, x: int) -> int: - print(f"In {x}") - for (source, dest, rnge) in self.maps: - print(f"Source {source}") + for (source, offset, rnge) in self.maps: if x >= source and x < source + rnge: - return dest + (x - source) + return x + offset return x - # index = bisect.bisect_left(self.maps, (x+1,0,0)) - # index -= 1 - # if index < 0: - # return x + # index = bisect.bisect_left(self.maps, (x+1,0,0)) - 1 + # # index -= 1 + # # if index < 0: + # # return x # - # source, dest, id_range = self.maps[index] - # if x < source + id_range: - # return dest + (x - source) + # source, offset, id_range = self.maps[index] + # if x >= source + id_range: + # return x + # # if x < source + id_range: + # return x + offset # return x + # + def merge(self, other: Map) -> None: + newmappings = [] + for osource, ooffset, orange in other.maps: + for ssource, soffset, srange in self.maps: + if osource >= ssource and osource <= ssource + srange: + pass + + + + + def __repr__(self) -> str: l = [] - for k, v, x in self.maps: - l.append(f"{k} - {k + x}: {v} - {v + x}") + for k, offset, x in self.maps: + l.append(f"{k} - {k + x - 1}: {k+offset} - {k+ offset + x - 1}") return f"Map({', '.join(l)})" @@ -55,9 +83,10 @@ class Problem: 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})") + # print(f"{target}({output_value})") output_value = self.maps[(target, new_target)][output_value] - print(f"{new_target}({output_value})") + # print(f"{new_target}({output_value})") + # self.cache[(old_value, target)] = (output_value, new_target) target = new_target return output_value @@ -94,23 +123,62 @@ class Day05(AocSameParser[Problem], Aoc2[Problem, Problem]): return Problem.from_input(inpt) def part1(self, inpt: Problem) -> int: - return min(inpt.convert("seed", "location", x) for x in inpt.seeds) + # print([inpt.maps["seed", "soil"][x] for x in range(100)]) + # + # print(inpt.maps["soil", "fertilizer"]) + # print(inpt.maps["soil", "fertilizer"][14]) + # print([inpt.maps["soil", "fertilizer"][x] for x in range(100)]) + 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]) + order = [("seed", "soil"), ("soil", "fertilizer"), ("fertilizer", "water"), ("water", "light"), ("light", "temperature"), ("temperature", "humidity"), ("humidity", "location")] + seed_iter = iter(inpt.seeds) + seeds = list(zip(seed_iter, seed_iter)) + for translation in order: + print(translation) + print(seeds) + new_to_convert = [] + current_map = inpt.maps[translation] + # print(seeds[1]) + # print(current_map) + for seed in seeds: + cur_range_start, cur_range_range = seed + cur_end = cur_range_start + cur_range_range + index = current_map.find_bucket(cur_range_start) + if index is not None: + # print(current_map.maps[index]) + section_start, section_offset, section_range = current_map.maps[index] + section_end = section_start + section_range + + if cur_end <= section_end: + new_to_convert.append((cur_range_start + section_offset, cur_range_range)) + else: + # split + new_to_convert.append((cur_range_start + section_offset, section_end - cur_range_start)) + if index == len(current_map.maps) - 1: + new_to_convert.append((section_end, cur_end - section_start)) + else: + next_start, next_offset, next_range = current_map.maps[index + 1] + next_end = next_start + next_range + new_to_convert.append((section_end + next_offset, cur_end - section_start)) + if cur_end > next_end: + print("Oh no") + + else: + new_to_convert.append(seed) + seeds = new_to_convert + + + + + # return min(inpt.convert("seed", "location", x) for x in seeds) def main(): day5 = Day05() - day5.run_example_2() + print(day5.run_example_2()) if __name__ == "__main__":