The previous elf sent you to see a gardener elf that needs your help.
There is a problem with this year’s planting of seeds.
Your input is a guide that tells you which seeds to plant.
It also lists what type of soil to use with each kind of seed,
what type of fertilizer to use with each kind of soil,
what type of water to use with each kind of fertilizer, and so on.
Every type of seed, soil, fertilizer and so on is identified with a number
An example input looks like this:
The guide first lists which seeds should be planted.
What follows are a bunch of maps that tell you how to convert a number of a certain type to a number of a different type.
Instead of having one rule per number, the rule lines in a map apply to a range of numbers.
Each rule in a map has 3 numbers:
The destination range start
The source range start
The range length
Consider again the example seed-to-soil map, it has 2 rules:
50 98 2
52 50 48
For the first rule, the three parts are:
Destination range start: 50
Source range start 98
Range length 2
So that rule maps to:
Destinations: 50, 51
Sources: 98, 99
A source number that falls in the range, gets converted to a destination number with the same offset.
Applying that rule:
Seed number 98 maps to soil number 50
Seed number 99 maps to soil number 51
If a number has no rule that applies to it, it remains unchanged.
So seed number 10 maps to soil number 10.
Part 1
The question asks what the lowest numbered location where a seed will be planted is.
To do this, we need to convert each seed number through every category until we end up with a location number.
In this example, the corresponding types are:
Seed 79, soil 81, fertilizer 81, water 81, light 74, temperature 78, humidity 78, location 82.
Seed 14, soil 14, fertilizer 53, water 49, light 42, temperature 42, humidity 43, location 43.
Seed 55, soil 57, fertilizer 57, water 53, light 46, temperature 82, humidity 82, location 86.
Seed 13, soil 13, fertilizer 52, water 41, light 34, temperature 34, humidity 35, location 35.
Option 1: for loop
First up, parsing the input into useful data!
I want to end up with a list of seed numbers, and a list of maps.
Each map holds a list of rules.
To not confuse what’s a destination and what’s a source while coding, I created a Rule data type for this.
Now I can access a destination with rule.destination, and not rule[0] like I would have to do if I stored the rule in a list too (or was it rule[1]? I forget).
The order of the rule maps in the input is sequential, how considerate of the puzzle creator.
This means I can ignore the headers of each map.
That order is:
seed to soil
soil to fertilizer
fertilizer to water
water to light
light to temperature
temperature to humidity
humidity to location
Next, the part where I calculate the location every seed is planted at.
I keep track of the minimum location and update it when a location is calculated.
some pseudocode:
Translated to valid Rust code:
Code
Option 2: An iterator chain
The iterator chain has less “bookkeeping”, no more keeping track of a curr, and a min variable, the iterator adapters take care of that.
Code
Part 2
Turns out we read the list of seeds wrong!
The “seeds:” line describes pairs of numbers.
The first is the start of a range
The second is the lengths of that range
For example: “seeds: 79 14 55 13”
Describes 2 ranges of seeds to be planted:
Seeds numbered 79 to 92
Seeds numbered 55 to 67
The question asks what the lowest numbered location where a seed will be planted is.
The brute-force approach would be to expand the list of seeds from part 1 to include all seeds.
Then run the exact same logic as in part 1.
But that solution takes a long time to run, and takes a lot of memory to complete.
I tried, but my computer was not beefy enough.
So instead of operating on single numbers, I operate on ranges of numbers in part 2.
A Range struct allows me to stay organized while I code and avoid accessing start and end numbers via an index: