Metadata
-
Date
-
Tagged
-
Part of series
- Advent of Code 2023 Day 1
- Advent of Code 2023 Day 2
- Advent of Code 2023 Day 3
- Advent of Code 2023 Day 4
- Advent of Code 2023 Day 5
- Advent of Code 2023 Day 6
- Advent of Code 2023 Day 7
- Advent of Code 2023 Day 8
- Advent of Code 2023 Day 9
- Advent of Code 2023 Day 10
- Advent of Code 2023 Day 11
- Advent of Code 2023 Day 12
- Advent of Code 2023 Day 13
- Advent of Code 2023 Day 14
- Advent of Code 2023 Day 15
- Advent of Code 2023 Day 16
- Advent of Code 2023 Day 17
- Advent of Code 2023 Day 18
- Advent of Code 2023 Day 19
- Advent of Code 2023 Day 20
- Advent of Code 2023 Day 21
- Advent of Code 2023 Day 22
- Advent of Code 2023 Day 23
- Advent of Code 2023 Day 25
-
Older post
-
Newer post
Advent of Code 2023 Day 9
Day 9: Mirage Maintenance
https://adventofcode.com/2023/day/9
You got out of the sandstorm and arrive at an oasis.
You gather some data on the oasis by tracking some datapoints, that’s today’s input.
An example input looks like this:
Each line in the report contains the history of a single value
Part 1
You want to predict the next value for each datapoint.
The question asks what the sum is of all next values.
To extrapolate the next value of a line, you start by making a new sequence with the difference at each step. You do this until all numbers in the new sequence are zeroes.
In the example input, for the first line:
Now to find the next value in the original sequence, start by adding a zero to the end of the last line.
This lets you figure out the last value on every previous line, until you get to the very first line (Nicky’s note: I smell recursion).
Also, I recognize this from math class! Pascal’s triangle. I don’t remember if there is a clever way to determine a specific value though, so I’m going to code up a brute-force solution and see how that works out. (spoiler: it worked out)
Option 1: imperatively
- I gather each line into a list of numbers.
- For each line, I figure out what the next number would be.
- I sum those numbers.
It’s the second step that’s the interesting part.
It’s in an infinite loop.
In that loop I build the new sequence of differences from a starting sequence (it starts as line in the input).
- If all numbers in that new sequence are 0, I’m done and break out of the loop.
- If not, I set the starting sequence to the sequence of differences, and do it all again!
I keep track of all numbers at the end of a sequence while looping. The next number in a sequence is the sum of its last number + all last numbers in sequences it generates.
To demonstrate, the example for line 3 in the example input:
Pointing your attention to the last number on every line. And checking what I’ve said above: “The next number in a sequence is the sum of its last number + all last numbers in sequences it generates.”
- 68 = 45 + 15 + 6 + 2
- 23 = 15 + 6 + 2
- 8 = 6 + 2
- 2 = 2 + 0
- 0 = 0
Code
Bonus: reuse memory
The same code, but keeping some variables around and reusing them. And indexing into arrays. The result is slightly faster code that uses less memory.
Code
Option 2: recursion
The solution I wrote first, shame it’s significantly slower than the imperative versions, because it reads so nice.
Helpers
A function that takes a line of numbers as a string, and turns it into a vector of integers:
A function that returns a list of all differences in a sequence:
The interesting part, the recursive part! A function that returns the next number in a sequence.
If all numbers in the original sequence are 0, the next number is 0 and I break. This is the base case that stops the recursion.
Otherwise, I calculate the list of differences. The next number is the next number in that list of differences plus the last number in the sequence that was passed in.
Code
Part 2
If we can figure out the next number in a sequence, how about the previous number?
The question asks what the sum is of all previous values.
Some copy pasting, some minor changes, and voila!
Now a previous number is the difference between a first number and the previous number from the next line.
The third line in the example again, with special attention to the first number of each line:
- 5 = 10 - 5
- 5 = 3 - -2
- -2 = 0 - 2
- 0 = 0
Option 1: imperative
I only coded the version that reuses memory, the other one is trivial to make from this one.
Code
Option 2: recursive
- The
nums
helper gets reused. - The
differences
helper gets reused. - The
next_num
helper gets replaced by aprev_num
one.