#!/bin/python3 import sys import re # i want to throw up numbers = [int(x) for x in input().split(":")[1].split()] seed_ranges = [] for x in range(0, len(numbers), 2): seed_ranges.append((numbers[x], numbers[x] + numbers[x+1],)) STEPS = [ 'seed', 'soil', 'fertilizer', 'water', 'light', 'temperature', 'humidity', 'location', ] maps = [] current_map = {"from": "", "to": ""} for line in sys.stdin: line = line.strip() if len(line) == 0: continue if "map:" in line: current_map["from"], current_map["to"] = line.split()[0].split("-to-") else: dest_start, source_start, range_len = [int(x) for x in line.split()] current_map["src_range"] = (source_start, source_start + range_len,) current_map["dest_range"] = (dest_start, dest_start + range_len,) current_map["offset"] = dest_start - source_start current_map["length"] = range_len maps.append(dict(current_map)) output_ranges = [] for inital_range in seed_ranges: ranges = [inital_range] # print(f"------ NEXT INPUT RANGE SET: {ranges} -------") for step in STEPS[:-1]: # print(f"[{step}] {len(ranges)} input ranges: {ranges}") current_step_maps = [m for m in maps if m["from"] == step] # print(f"current_step_maps\n\t" + '\n\t'.join([str(d) for d in current_step_maps])) next_ranges = set() for range in ranges: applicable_maps = [m for m in current_step_maps if \ m["src_range"][0] <= range[0] < m["src_range"][1] or \ m["src_range"][0] < range[1] <= m["src_range"][1]] applicable_maps = sorted(applicable_maps, key=lambda d: d["src_range"][0]) index = range[0] # print(f"map range {range} using maps\n\t" + '\n\t'.join([str(d) for d in applicable_maps])) while index < range[1]: cover_step = 0 offset = 0 if len(applicable_maps) == 0: # print("> no more maps ahead!") cover_step = range[1] - index offset = 0 else: next_map = applicable_maps[0] if next_map["src_range"][0] <= index < next_map["src_range"][1]: # print(f"> {index} in map range") cover_step = next_map["src_range"][1] - index offset = next_map["offset"] applicable_maps.pop(0) else: # print("> skipping until next map") cover_step = next_map["src_range"][0] - index offset = 0 cover_step = min(cover_step, range[1] - index) next_ranges.add((index + offset, index + cover_step + offset,)) # print(f" creating a range with length {cover_step} and offset {offset}:") # print(f" {(index, index + cover_step,)} -> {(index + offset, index + cover_step + offset,)}") index += cover_step # print(f"> end of input range reached") # print("\n") ranges = sorted(list(next_ranges), key=lambda t: t[0]) output_ranges += ranges seed_ranges = sorted(seed_ranges, key=lambda t: t[0]) output_ranges = sorted(output_ranges, key=lambda t: t[0]) for range in seed_ranges: intersections = [m for m in output_ranges if \ range[0] <= m[0] < range[1] or\ range[0] < m[1] <= range[1]] if len(intersections) == 0: continue intersections = [ (max(m[0], range[0]), min(m[1], range[1]),) for m in intersections ] intersections = sorted(intersections, key=lambda t: t[0]) print(f">> {intersections[0][0]}") break