You’ve probably guessed by now that I really like Advent of Code, Eric Wastl’s annual collection of Christmas-themed programming puzzles. Even ignoring the puzzles, the experience is alluring. The silly but surprisingly elaborate narrative tying the puzzles together, the burgeoning community, the steady increase in difficulty, and the soothing blue-and-gold design of the site all combine to make the event something special. But the puzzles are the main event, so you ought to know something about them before diving in.
With a hundred-odd stars across three years, I thought I’d offer some advice.
To have an enjoyable experience, I don’t think you need anything more than familiarity with at least one programming language. You certainly don’t need formal computer science education, knowledge of math theory, or any experience with competitive programming, though all those things are helpful. You just need to know how to take a problem statement, come up with a plan to solve it, and translate that plan into code. None of that is easy, but Advent of Code is a great way to practice.
Here are some less obvious pointers.
Be absolutely sure you understand what is being asked.
Puzzles often contain complicated rules with subtle but important edge cases. The text is usually careful to note these; if not, they often appear in the examples provided. Still, Wastl has remarked that, for any given sentence of the puzzle text, there is always at least one player who ignores it, to their cost. More times than I can count, I’ve missed some crucial nuance and wasted time on unworkable solutions. Don’t be like me. Don’t start solving a puzzle until you’ve resolved all your questions about how you should interpret the input, and remember that an extra minute spent skimming the puzzle text could save you an hour of fruitless coding.
Resist the temptation to pre-solve the second part.
I’d better make this code robust to handle the second part, you tell yourself. I’ll look so clever when I solve it just by tweaking a parameter in my solution to the first part! Stop right there. The whole point of the second part is that you can’t plan for it. It could take any one of dozens of forms. It might ask you to find the highest of something instead of the lowest, remove a constraint that made the problem simpler, impose a new constraint that makes it more complicated, or even require you to use the input in a completely different way than the first part. Beyond wrapping your code in functions or classes you can reuse, you can’t prepare for all these scenarios, and you’ll only waste time if you try.
The exception is puzzles whose first parts tell you to ignore some part of the input. In that case, the second part is all but certain to use the full input, and the increase in scale could well break a naive but inefficient algorithm that works on the first part.
Look out for some recurring themes
175 puzzles in, Wastl still manages to avoid merely recycling old ones. But naturally, the same kinds of problem crop up again and again, albeit always with a fresh variation or two. In any given year, expect to see at least one appearance each of the following:
- Evaluating and parsing a made-up assembly language
- Finding the shortest path between a certain pair of nodes on a graph
- String manipulation, possibly involving regular expressions
- Some application of combinatorics
- A variation on Conway’s game of life
Puzzles become a lot less daunting when you recognize them as new twists on familiar concepts. Moreover, these are all well-studied problems in computer science, so you can easily find advice or pseudocode for useful algorithms if you get stuck.
Be lazy.
Efficient code does as little work as possible. Advent of Code doesn’t expect you to aggressively optimize your code, but it does reward you for finding clever ways to avoid unnecessary computations. If you’re trying combinations of values to look for the answer, for instance, you can greatly speed up your code if you find an easy way to ignore combinations that can’t possibly yield the right answer. In a similar vein, resist the urge to just simulate a puzzle that asks for the outcome of a game or process. If you can think of a way to compute the answer directly, your code will probably run much faster. And beware: some puzzles require it. I’ve come across a few where a naive algorithm worked on the first part, but the second part changed the rules so a non-optimized approach became hopelessly slow.
Advent of Code isn’t intended to require dirty optimization hacks, but it does test your ability to think of subtler approaches than brute force.
Don’t make it into work.
Advent of Code is, above all, fun - a chance to write code that solves silly problems about made-up Yuletide adventures. Of course, it’s also an opportunity to practice writing good code to diverse and difficult specifications, but that’s secondary. Don’t stress about efficiency, style, or refactoring; nobody is going to hound you for breaking code quality guidelines on Christmas puzzles.
And if you get stuck, do something else for awhile - you’ll get that star eventually. It’s not a sign you’re dumb or bad at coding; the puzzles are devised by a clever software engineer to challenge an audience largely composed of software engineers, after all. (That doesn’t mean I’m not dumb, mind you - you just have to look elsewhere for proof of that assertion).
If you’re unsure whether to take part, just give it a try. I did, and the experience spurred me to learn new languages and start thinking seriously about the code I wrote. The first puzzle of each year is usually simple, and you’re not obliged to continue if you don’t enjoy it. But if you do enjoy it, there’s no telling how far your newfound interest will carry you. I hope you found this advice useful, or at least entertaining. See you in December!