Josiah Winslow solves Advent of Code

Mirage Maintenance

Published: 2025-10-17 Original Prompt

Part 1

This puzzle doesn’t really call for much; after parsing the input as a list of value histories (i.e. a list of lists of ints), the only thing left to do is sum up extrapolated values for each history.

2023\day09\solution.py
class Solution(StrSplitSolution):
def part_1(self) -> int:
histories = [list(map(int, line.split())) for line in self.input]
return sum(extrapolate(h) for h in histories)

The only thing that’s missing is the extrapolate function itself, but it doesn’t call for much either. I’m aware of a neat formula I could use for this,1 but instead I’ll use a recursive definition.

not any(history) is a neat shorthand for checking if history contains all 0s,2 and itertools.pairwise loops through the pairs of history values so we can gather their differences.

2023\day09\solution.py
from itertools import pairwise
def extrapolate(history: list[int]) -> int:
if not any(history):
return 0
diffs = [b - a for a, b in pairwise(history)]
return history[-1] + extrapolate(diffs)

Short and sweet!

Part 2

Although it seems like we’d need to rewrite our extrapolate function to also extrapolate backwards, we don’t need to. We can just reverse the history list before we pass it to extrapolate! (After all, moving backwards is basically moving forwards, but in reverse… if that makes sense.)

2023\day09\solution.py
...
class Solution(StrSplitSolution):
def _solve(self, reverse: bool) -> int:
histories = [list(map(int, line.split())) for line in self.input]
return sum(extrapolate(h[::-1] if reverse else h) for h in histories)
def part_1(self) -> int:
return self.solve(reverse=False)
def part_2(self) -> int:
return self.solve(reverse=True)

Tip

A common idiom for reversing a list s in Python is s[::-1] — that is, getting values from one end to the other, stepping by -1 each time.

Lists also have a reverse method (called like s.reverse()), but it operates in-place and returns None; on the other hand, s[::-1] returns a reversed copy of the list.

If you simply need to iterate over the items of s in reverse order, reversed(s) should be used instead, as it neither modifies the list nor copies it.

And just like that, we’re already done! I’m surprised we could get away with so little code.

Footnotes

  1. I saw this solution by u/1str1ker1 on Reddit that uses the following formula, which doesn’t require recursion or taking differences:

    I think it’s a beautiful formula, but I don’t quite understand how it works.

  2. This is because any checks whether any items in an iterable are considered “true”, and 0 is considered “false”.