AOC 23 - Day 09 Mirage Maintenance
I liked this day. It was simple, since the solution was given with the rules. But it made me learn a new thing: how to find the next number of a sequence, which is cool !
Part 1
Rules
So we need to calculate the next number of a sequence.
I had no idea how to do this but luckily, the description of today give us a method:
For a line of digits, we need to get the differences between each number.
For example, 1 3 6 10 15 21
would give 2 3 4 5 6
.
We then calculate the differences from this new list, until we have a list of only zeroes:
2 3 4 5 6
-> 1 1 1 1
1 1 1 1
-> 0 0 0
In this case, we ends with 4 lists:
1 3 6 10 15 21
2 3 4 5 6
1 1 1 1
0 0 0
We then have to compute the next number for each line. To find a value, we needs to sum the value to it's left, and the right most value of the previous line.
For example here, we would do the following:
Line 3, A
is gonna be the sum of 0
(right most value from line 4) and 1
(the value to it's left), which gives us 1
1 1 3 6 10 15 21 C
2 2 3 4 5 6 B
3 1 1 1 1 A
4 0 0 0
1 1 3 6 10 15 21 C
2 2 3 4 5 6 B
3 1 1 1 1 1
4 0 0 0
B
is the sum of 6
(left value) and 1
(the right most value we just computed), givin us 7
:
1 1 3 6 10 15 21 C
2 2 3 4 5 6 7
3 1 1 1 1 1
4 0 0 0
We can then find the value of C
by summing 21
and 7
, for a final result of 28.
For a given list of sequences, we need to sum up the next number for each line.
For example with
0 3 6 9 12 15
1 3 6 10 15 21
10 13 16 21 30 45
The next numbers are 18
, 28
and 68
, for a sum of 114
Code
Let's start by parsing the input, which is very straightforward today:
=
return
We then wants a function to expand a list of numbers, until we reach a sequence containing only zeroes is reached.
To do this, we just need to iter on a list pair by pair, push their differences into a new list, start again with this new list until the end condition is reached:
"""Generates a list of difference sequences from an input sequence
until a sequence of all zeros is reached.
Example:
>>> get_sequence_differences_list([1, 3, 6, 10, 15, 21])
[[1, 3, 6, 10, 15, 21], [2, 3, 4, 5, 6], [1, 1, 1, 1], [0, 0, 0]]
"""
=
=
=
return
"""s -> (s0,s1), (s1,s2), (s2, s3), ..."""
=
,
return
The pairwise
function is provided by itertools list of recipes.
Then, getting the last digit for this sequence consists of iterating on the expanded sequence in reverse, using indexing to get the previous and left numbers, and append their sum to the current sequence:
=
# Find next number from last to first
=
=
return
We then just have to apply this function to each sequence, and sum it's return to solve part 1:
=
return
Part 2
Rules
The twist of this part is that we have to extrapolate backward: instead of taking the rightmost previous number and the left number, before inserting it to the right, we do the opposite: we should instead fill in new first values for each previous sequence, with the leftmost numbers.
This means that with
10 13 16 21 30 45
3 3 5 9 15
0 2 4 6
2 2 2
0 0
We will instead have this result:
5 10 13 16 21 30 45
5 3 3 5 9 15
-2 0 2 4 6
2 2 2 2
0 0 0
Code
With the previous implementation, we just have to change the code from
get_last_sequence_number
to update the indexing so we take the first instead of the last element to retrieve the numbers, and that we need to insert at the beginning of the list:
=
# We index by 0 instead of -1
=
=
# And be careful to insert the difference at the beginning of the list
return
Then, as for part 1, solving part 2 just consists of getting the sum each sequence:
=
return
That's it for today !
The full code is available here