Wait For It
2025-10-14 Original Prompt Part 1
I have to admit, my initial solution for this puzzle was a bit on the complicated side. I was trying too hard to think of a clever solution. Maybe it’ll come to me if I… wait for it.1
For now, let’s do the simplest thing I can think of. Let’s just count the number of different button-holding times that beat the record distance.
If the time spent holding the button is sum up the cases for which the formula’s
result is greater than the record distance.
def num_race_wins(time: int, distance: int) -> int: return sum(b * (time - b) > distance for b in range(time))Note
This works because bool is a subclass of int;
if you do number-like things to False and True, they get treated like the
integers 0 and 1 respectively. So for example, sum(n > 42 for n in values)
will count the number of values in values that are greater than 42.
Armed with this function, we can solve Part 1 very easily. zip runs through
the times and distances in parallel (keeping the time and record distance of
each race together), and we just need to pass them to our function and wrap it
in math.prod!
from math import prod
class Solution(StrSplitSolution): def part_1(self) -> int: times, distances = [ list(map(int, line.split()[1:])) for line in self.input ] return prod( num_race_wins(time, distance) for time, distance in zip(times, distances) )Part 2
Can I stick with brute-forcing this time? Yes; I just need to str.join
the input numbers to get single time/distance numbers.
...
class Solution(StrSplitSolution): ...
def part_2(self) -> int: time, distance = [ int("".join(line.split()[1:])) for line in self.input ] return num_race_wins(time, distance)Is it quick enough? Also yes; both parts run in ~2.34 seconds on my machine.
Will I stick with brute-forcing? No; I feel like I was onto something with my initial solution. And if I implement my idea well, it should spit out an answer immediately, and I won’t have to…wait for it.2
Here be algebra
If all you wanted was an answer, you can stop here. If you want to see the faster answer I came up with, continue reading… but be wary if you weren’t that good at high school algebra.
If we take our formula from before (
I noticed this when I wrote my initial solution, but directly calculating the number of integer solutions to this inequality is harder than it sounds. (Or at least, I couldn’t figure it out day-of.)

Looking at a plot of this quadratic inequality, we can see that we’ll find
integer solutions if
If we apply Po-Shen Loh’s quadratic method
here,4 the halfway point math.floor
and math.ceil to
guarantee that they’re outside of the range). Finally,
This allows us to implement the num_race_wins function like so:
from math import ceil, floor, prod, sqrt
def num_race_wins(time: int, distance: int) -> int: # NOTE The distance the boat travels is b * (t - b), where b is the # time spent holding the button, and t is the total race time; we # want the amount of b values where this distance is greater than # the record. To do this, I use some carefully handled algebra. halfway = time / 2 offset = sqrt(halfway * halfway - distance) lower_root = floor(halfway - offset) upper_root = ceil(halfway + offset) # NOTE This is the length of the range, excluding the two endpoints. return upper_root - lower_root - 1A bit more algebra, but a much lower time complexity. Now both parts of my solution run in ~3 microseconds on my machine — almost six orders of magnitude faster than before!
Footnotes
-
Bad joke, I know. ↩
-
It’s even worse the second time! ↩
-
The roots themselves are not solutions, because by definition the Y-values there are 0. And 0 is not less than 0. ↩
-
I could’ve used the more
well-knowncommonly memorized quadratic formula, but I find Po-Shen Loh’s method much more simple to implement and easy to explain. ↩