diff --git a/day05/part2.py b/day05/part2.py index 5928fd8..49ce4d4 100644 --- a/day05/part2.py +++ b/day05/part2.py @@ -3,29 +3,10 @@ from typing import List, Tuple from tqdm import tqdm lines = (x.strip() for x in open("input.txt")) -seeds = () -current_map = "undef" -maps = {} -map_names = [] +seeds = list(int(y) for y in next(lines)[7:].split(" ")) +curr_map = None -for line in lines: - match line: - case "" | "\n": - continue - case x if x.startswith("seeds: "): - rest = x[len("seeds: "):] - seeds = tuple(int(y) for y in rest.split(" ")) - case x if x.endswith(" map:"): - rest = x[:-len(" map:")] - current_map = rest - maps[current_map] = [] - map_names.append(current_map) - case x if len(x) and x[0].isdigit(): - maps[current_map].append(tuple(int(y) for y in x.split(" "))) - case _: - pass - -def parse_map(value: List[Tuple[int, int, int]]): +def items_to_map(value: List[Tuple[int, int, int]]): curr = 0 out = [] for dest, src, size in sorted(value, key=lambda x: x[1]): @@ -37,36 +18,43 @@ def parse_map(value: List[Tuple[int, int, int]]): out.append((curr, 0)) return out -maps = {name: parse_map(value) for name, value in maps.items()} +def iter_maps(lines): + next_items = [] + for line in lines: + if len(line) and line[0].isdigit(): + next_items.append(tuple(int(y) for y in line.split(" "))) + elif len(next_items): + yield items_to_map(next_items) + next_items = [] + if len(next_items): + yield items_to_map(next_items) + def find_largest_smaller_value(sorted_list, x): low, high = 0, len(sorted_list) - while low < high - 1: mid = (low + high) // 2 if sorted_list[mid][0] <= x: low = mid else: high = mid - return sorted_list[low], low -def merge_list(curr_map, next_map): - next_mapping = [] +def merge_maps(curr_map, next_map): + merged_map = [] for i in range(0, len(curr_map)): dest_start = curr_map[i][0] + curr_map[i][1] dest_start_idx = find_largest_smaller_value(next_map, dest_start)[1] dest_end = curr_map[i + 1][0] + curr_map[i][1] - 1 if i + 1 < len(curr_map) else None dest_end_idx = find_largest_smaller_value(next_map, dest_end)[1] if dest_end is not None else len(next_map) - 1 for next_start, next_offset in next_map[dest_start_idx:dest_end_idx + 1]: - next_mapping.append((max(curr_map[i][0], next_start - curr_map[i][1]), curr_map[i][1] + next_offset)) - return next_mapping + merged_map.append((max(curr_map[i][0], next_start - curr_map[i][1]), curr_map[i][1] + next_offset)) + return merged_map -# merge lists into a single one -curr_map = maps[map_names[0]] -for name in map_names[1:]: - curr_map = merge_list(curr_map, maps[name]) + +for next_map in iter_maps(lines): + curr_map = next_map if curr_map is None else merge_maps(curr_map, next_map) result = float("inf")