import fileinput import sys input = fileinput.input() seeds = [int(seed) for seed in next(input).split()[1:]] next(input) next(input) def parse_map(input): try: while line := next(input).strip(): yield tuple(int(n) for n in line.strip().split()) next(input) except StopIteration: pass yield (0, 0, sys.maxsize) seed_to_soil = list(parse_map(input)) soil_to_fert = list(parse_map(input)) fert_to_water = list(parse_map(input)) water_to_light = list(parse_map(input)) light_to_temp = list(parse_map(input)) temp_to_humid = list(parse_map(input)) humid_to_loc = list(parse_map(input)) def transform_ranges(map, ranges): for start, length in ranges: # find the start of the range (dst_start, src_start, len) = next((dst, src, len) for (dst, src, len) in map if src <= start < (src + len)) end = start + length src_end = src_start + len # yield the starting range yield (dst_start + start - src_start, min(src_end, end) - start) # if range is not complete, recurse into the rest if end > src_end: yield from transform_ranges(map, [(src_end, end - src_end)]) def part1(): result = sys.maxsize for seed in seeds: soil = next(dst + seed - src for (dst, src, len) in seed_to_soil if src <= seed < (src + len)) fert = next(dst + soil - src for (dst, src, len) in soil_to_fert if src <= soil < (src + len)) water = next(dst + fert - src for (dst, src, len) in fert_to_water if src <= fert < (src + len)) light = next(dst + water - src for (dst, src, len) in water_to_light if src <= water < (src + len)) temp = next(dst + light - src for (dst, src, len) in light_to_temp if src <= light < (src + len)) humid = next(dst + temp - src for (dst, src, len) in temp_to_humid if src <= temp < (src + len)) loc = next(dst + humid - src for (dst, src, len) in humid_to_loc if src <= humid < (src + len)) result = min(result, loc) return result def part2(): result = sys.maxsize for start, len in zip(*(iter(seeds),) * 2): soils = transform_ranges(seed_to_soil, [(start, len)]) ferts = transform_ranges(soil_to_fert, soils) waters = transform_ranges(fert_to_water, ferts) lights = transform_ranges(water_to_light, waters) temps = transform_ranges(light_to_temp, lights) humids = transform_ranges(temp_to_humid, temps) locs = transform_ranges(humid_to_loc, humids) (loc, _) = min(locs) result = min(result, loc) return result print(part1(), part2())