day 05
if you give a seed a fertilizer
approach
the almanac is parsed into the seed list and a dict from map name to its (dest, src, length) rules. the seven category maps are applied in a fixed order.
part 1 pushes each seed through the maps one at a time and takes the minimum location. part 2 reads the seeds as pairs that describe ranges, so it moves whole intervals instead: transform_range finds a rule that covers the start or end of an interval, maps the overlapping part, and recurses on whatever is left over; pieces that no rule touches map to themselves. after the last map, the answer is the smallest interval start.
the trick
map ranges, not seeds: split each interval where it crosses a rule and shift the pieces.
python
def part2(mappings, seeds, categories):
intervals = []
for i in range(0, len(seeds), 2):
intervals.append((seeds[i], seeds[i] + seeds[i + 1] - 1))
for cat in categories:
nintervals = []
for s, e in intervals:
nintervals.extend(transform_range(mappings[cat], s, e))
intervals = nintervals
return min(inter[0] for inter in intervals)