The default fix for a slow script now seems to be more compute, or a wrapper written by a chatbot. Neither one changes the complexity of the code underneath. Algorithmic thinking in data science is the part that does, and skipping it means hoping the memory holds out until the script finishes.
I have watched sites fall over under load because someone reached for a nested loop where a hash set or a min-heap belonged. Last month I stepped away from a run of WooCommerce race conditions and spent a few evenings on Advent of Code 2025 instead. The elf framing is silly, but the puzzles are honest about arithmetic. Four of them stuck with me, mostly because the first solution that comes to mind is the one that fails.
Tachyon Manifolds and memoization
Day 7 is called Tachyon Manifolds. Beams split as they cross a grid, and the first thing most people write is unbounded recursion. What the puzzle actually wants is set algebra plus dynamic programming.
Overlapping beams should count once. Keep them in a list instead of a set and the work grows exponentially for no reason at all. An intersection does the deduplication for you:
import functools
def find_all_indexes(s, ch):
return {i for i, c in enumerate(s) if c == ch}
# Using set operations to handle beam intersection
hits = beam_ids.intersection(splitter_ids)
split_counter += len(hits)
# Reduction helps simplify complex branching logic
if hits:
new_beams = functools.reduce(lambda acc, h: acc.union({h - 1, h + 1}), hits, set())
Part Two adds parallel timelines, so the same path gets walked again and again. Without @lru_cache the recomputation is basically the whole runtime. The same mistake shows up in custom WordPress reporting plugins that work out recursive sales commissions, and memoization is the entire fix.
Building circuits with heaps and Union-Find
Day 8 connects electrical junction boxes by Euclidean distance. Sorting every possible pair works right up until the input grows, which is also true of the nearest-neighbor feature behind a store locator or a recommendation engine. A min-heap gets you the same answer without building that list at all.
Python’s heapq pops the smallest distance in O(log n). The harder half is joining everything into one circuit without closing a loop, and that is Kruskal’s algorithm.
Union-Find is how I have cleaned up hierarchical data in old WordPress databases, the kind where parent and child rows end up pointing at each other in a circle. It answers one question cheaply: are these two nodes already in the same component?
There is more on the profiling side of this in an earlier post on fixing slow Python code, if that is the part currently biting you.
Factory machines and linear programming
Day 10 cost me the most time. You configure factory machines to reach a target state in as few button presses as possible. Written as a search it never finishes. Written as mixed-integer linear programming it is a handful of lines.
A button that toggles three lights at once is modular arithmetic, not adjacency. A breadth-first search handles the sample input and then blows up on the real one. With scipy.optimize.milp you hand the solver a matrix and it comes back with the global minimum.
from scipy.optimize import milp, LinearConstraint, Bounds
import numpy as np
# Reformulating congruence Ax ≡ t (mod 2) as Ax - 2k = t
A_eq = np.hstack([A, -2 * np.eye(m)])
lc = LinearConstraint(A_eq, target, target)
res = milp(c=c, constraints=[lc], integrality=integrality, bounds=bounds)
Supply chain planning and portfolio allocation run on the same machinery. If your code is walking every combination, that is usually a sign the problem wants to be a linear model instead.
Reactor troubleshooting as network analysis
Day 11 counts paths through a reactor network. The same shape turns up in a telecoms grid or an ETL dependency graph. Run the depth-first search with an explicit stack and Python stops raising recursion depth errors on you, which anyone who has walked a deeply nested WordPress category tree has run into at least once.
Requiring a path to pass through specific nodes prunes most of the search space before you ever walk it. Recommender engines lean on the same trick, tracing valid paths through a graph instead of scoring everything in it.
If this kind of work is eating your week, I take it on as contract work. I have been building on WordPress since the 4.x days.
What stuck with me
None of these puzzles need a clever language feature. They need you to notice which problem you are holding: a set problem, a graph problem, an optimization problem. Once that is settled the library call is short, and usually someone has already written it. Get it wrong and you ship a nested loop that looks fine until the data grows.