# Advent of Code as a performance sport

> Puzzles unlock at 2pm in Tokyo, which makes December a lunch-break sport. Notes on the rig, the day 15 run that finished second globally, and why unreadable code is fine for exactly one month a year.

Author: Karan Vijayakumar
Published: 2025-12-21
Tags: advent-of-code, competitive-programming, tokyo, fun
Reading time: 7 min
Canonical URL: https://karanvk.me/blog/advent-of-code-leaderboard

---

Advent of Code unlocks at midnight US Eastern, which in Tokyo is 2pm. I want to start there, because it's the single most unfair advantage in this entire hobby and nobody in the leaderboard chat ever mentions it.

The people I'm competing with for those hundred slots are, in large numbers, sitting in a dark room in Europe or North America at one in the morning, running on adrenaline and whatever's left of the day. I'm at my desk in Shibuya, having eaten lunch, on my second coffee, with the low December sun coming in at that flat angle Tokyo gets in winter when the air goes dry and the sky stays cloudless for a week at a time. It is the best weather of the year here and it lines up perfectly with the best month of the year for this.

Fifteen minutes before unlock I put my headphones on and open a terminal. Everyone I know who does this seriously treats it as a nightly ritual. For me it's a lunch break. I don't think I'd have stuck with it otherwise.

## The rig

Nothing here is sophisticated, and the lack of sophistication is the point.

There's a template repo I've carried for a few years. One command scaffolds a day: a folder, a source file with the boilerplate already in it, an empty input file. A small fetcher pulls the input using my session cookie, so I never touch the browser once the page is open. That saves maybe eight seconds, which sounds absurd until you've lost a placement by four.

The parse helpers are the real asset, and they're all tiny. Grid of characters into a flat array with a width, because I got tired of nested vectors. All the integers out of a line, signs included, ignoring whatever punctuation the story wrapped around them. Blocks split on blank lines. Neighbors in four directions and eight, bounds-checked. A grid printer, because half of debugging a December puzzle is looking at the thing.

Zero tests. None. I've never written a test in an Advent of Code repo and I'm not going to. The feedback loop is: run it on the sample, look at the number, compare it to the number in the problem text. If those match, run it on the real input and submit. Anything more ceremonious is time I'm spending on my tooling instead of on the puzzle, and the puzzle is the sport.

I also keep a file of things I always get wrong. Off-by-one on inclusive ranges. Rows and columns transposed in my own neighbor offsets. Forgetting that part two's answer overflows a 32-bit integer. I reread it on the first of December, every year, and it does not help, and I keep doing it anyway.

## Day 15

Monday the fifteenth. 2pm. The page loads and I read.

Reading is the part people underrate. Not skimming: reading, once, properly, in about a minute. There's a specific failure I've trained myself out of, which is starting to type at the halfway point of the problem statement because you think you've recognized the shape. You lose forty seconds that way if you're lucky and four minutes if you aren't.

So I read it, and about two thirds through, the shape did land. It was dressed up as a grid simulation, elves and a machine and some seasonal nonsense, but the constraints gave it away: the state you had to track wasn't just your position, it was your position plus a small set of things you'd collected, and the set was small enough to fit in a bitmask. Which makes it a shortest path over an expanded state space, and that's a breadth-first search with a wider key. I've written that search dozens of times. My hands know it.

Part one went fine. Nothing to report, which is the best possible outcome.

Part two was the one worth remembering. It widened the state, as part twos do, and I had the whole thing typed in maybe three minutes, and it printed a number that was wrong. Not garbage. Slightly, plausibly wrong, which is the worst kind, because plausible means the algorithm is probably right and something in the plumbing isn't.

Forty seconds. That's what it cost me, and I know the number because I went back through my shell history afterward like a person reviewing game tape. I'd written `dy` where I meant `dx` in one of four neighbor offsets. One character. Exactly the mistake that is written down in the file I reread on the first of December. I stared at the output, ran the sample again, saw the path bending in a way it shouldn't, found it, fixed it, ran it, submitted.

Green.

Then the thing you do, which is refresh the leaderboard immediately, knowing it's undignified.

Second. Globally, second, on the day, by something like six seconds on part two.

I sat there in an office in Shibuya, in the afternoon, next to a konbini onigiri I'd bought at 1:40 and never opened, grinning at a terminal like an idiot. Nobody around me knew anything had happened. There was no way to explain it that wouldn't have taken ten minutes and sounded insane. A colleague asked if I was okay. I said yes, I'm great, and went back to work.

I've had bigger professional wins this year, by any reasonable measure. I'm not sure any of them produced that exact feeling. Six seconds.

## Why this feels like on-call

There's a thing speed-solving shares with incident response and it isn't the algorithms.

It's clock-calm. The state where a timer is running, you know it's running, you can feel it, and your hands stay slow anyway. That's trainable, and Advent of Code is a remarkably safe place to train it, because the stakes are a number on a webpage instead of somebody's revenue.

The specific transferable moves, at least for me:

When you're stuck, stop typing and reread the statement. In an incident, stop typing and reread the alert. I have lost more time to theorizing past the text in front of me than to any actual technical difficulty, in both contexts.

Never rewrite under a clock. The instinct when output looks wrong is to blow it up and start over clean, and it's almost always the wrong call, because the thing you're about to rebuild is 95% correct and you're about to reintroduce three bugs you already fixed. Bisect instead. Print the intermediate state. Find the one character.

And verify small. On day 15, the sample grid was the whole reason I found the transposition in forty seconds instead of four minutes. In production that's the same instinct as reproducing against one tenant before touching the fleet.

The honest asymmetry, though, is worth stating: in a puzzle, you know a solution exists, you know it's findable in minutes, and someone has already verified the answer. None of that is true at 3am. That certainty is a large part of what makes contests fun and it's precisely the part production never gives you. Anyone who tells you the two experiences are the same has been lucky in one of them.

## The confession

I opened day 15 again about an hour later, to clean it up for the repo.

I could not read it.

The grid was `g`. The queue was `q`. There was a variable named `m` that meant mask in one place and, I'm fairly confident, something else six lines down. There was a while loop with a comment above it that said, in full, `// ??`. I had written this code sixty minutes earlier and I had to trace through it like a stranger's.

And I've decided that's fine. Genuinely, not defensively.

I've spent years unlearning exactly these habits at work, for good reasons, after being paged at 2:40am by a rate limiter I'd made too clever to read. That lesson holds. But December code doesn't have to be January code. There is no second reader. There is no on-call rotation. Nothing depends on this and nothing ever will, and the entire artifact exists to have been produced quickly, once. Optimizing it for maintainability would be optimizing for a reader who does not exist.

The discipline isn't never writing like that. It's knowing which month it is.

I'll be back next December, at 2pm, with a cold onigiri.
