Advent of Code 2023 - Day 5If You Give A Seed A Fertilizer
| Problem statement | Source code | Tags: MathematicsPuzzle
Part 1
Let me reformulate the problem. There is a list of functions, each piecewise linear of the form
We need to map a list of numbers through these functions. To map a single number, we just need to check which piece applies to it, and add the corresponding to it. It's not a bad idea to use binary search, but since is small, a linear search suffices.
(My input is parsed to a list of dataframes, each one containing columns from_start, from_end, and diff, which are , , and respectively.)
Part 2
Now we need to map ranges of numbers. Because the ranges are big, it's infeasible to map each number individually. However, there's a key observation: most points' relative order do not change. For example, if and are both in the target range and are mapped by the same function piece for every function, then their relative order never changes, and is always larger than . When can become a candidate for the minimum mapped value? Only when and are mapped by different pieces of some function—in other words, when is the ending point of one piece and is the starting point of another piece.
So, consider one mapping step:
We can map each range one by one. First, we find all pieces that overlap with the input range. The first and last piece may not be fully covered by the range; they are clipped to the input range. For example, in the diagram above, the blue range is mapped by a single piece that's greater than the range, so the piece is clipped. We iterate through these pieces in order. It is guaranteed that the pieces are fully covered by the input range (although might not be vice versa). Therefore we can just apply the mapping to the endpoints of each piece to get its output range. If there's a gap between this piece and the previous one (including at the beginning and end of the input range—we can pretend there's a piece that ends immediately before the input range, and another that starts immediately after), the gap is filled by an identity mapping.