Skip to content
advent of code 2023

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)