Advent of Code is an advent calendar of coding puzzles – one puzzle appears every day from 1st to 25th December. Each puzzle is in two parts; solving the first part (by writing some code to work out the right answer, and pasting it into the site) gets you a star, and unlocks the second part, which usually needs you to adapt the code you just wrote to account for some tricky new twist. If you complete both parts of all the puzzles, you’ll rack up an extremely satisfying 50 stars.
It’s free to take part – you can donate to support the site if you like – and it’s very popular: In 2022, over 270 thousand people completed the first puzzle and gained a star. Those participants are a very supportive community; you’ll find people on Reddit, YouTube, blog posts and lots of social media sites using the #AdventOfCode hashtag. People share their solutions, give spoiler-free advice or hints, and encourage people to learn and get creative. It’s such fun, and amazing to see the way people approach things.
I’m writing this post in early November, which might seem too soon to think about a Christmas-themed event … but if this talk video is right then the site’s creator, Eric Wastl, has been working on this year’s challenge since August. I love the thought and attention that goes into this challenge every year – the puzzles ramp up and down in difficulty, covering a range of different skills you might use, all with a very charming story to tie them together. It’s worth having a think now about whether you’d like to try it out this year – there’s time to look into how it works, set up a programming environment, remember (or learn) how writing code works, and get ready to clear a bit of time in December.
Would you like to give it a go?
To get started, go to https://adventofcode.com/ and choose “Log In” – and you can create a login using a Google account, or various other services you might use anyway. This year’s puzzles will start appearing from December 1st, but you can have a look and try solving any past years – there’s no time limit on any of them.
The main challenge – solve the 2 parts of each puzzle, on the day they’re released – is really, really difficult. Some days are simple, but later ones need all kinds of lateral thinking and ideas from maths, computer science, and other areas. I don’t think I know anyone who’s managed that complete timeboxed challenge. But that’s fine!
If you think the idea sounds intriguing, go ahead and try it. They’re very satisfying puzzles – and getting just a little bit further than you thought you’d be able to can teach you some new skills, and give you a benchmark to come back and beat next year if you want to. There’s no time limit – so do just one star, even if finding time for it takes you more than one day, and see if you like it.
You can use any programming language you like. Everyone gets the same puzzle, but their own personal “puzzle input” – a file you take and use to work out the solution however you like. Once you have the solution, you paste it in … and hopefully get one of those coveted stars and reveal the plot twist of part 2 of that puzzle.
If you haven’t programmed before, or did a long time ago, I’d encourage you to have a go if you’re at all tempted. One star is more than most people manage, and you might find it a fun learning experience that tempts you to get more. Not sure where to start?
Python is beginner-friendly (and also one of the most popular languages in the world for professionals). Visual Studio Code is a free tool that lets you write Python programs – this tutorial will get that set up, and you should definitely get unit testing set up too (the advent of code puzzles are very helpful for testing, they give examples of inputs and outputs so you can check your code’s working as you’d expect). For a friendly, free intro to how Python works (and how programming works at all), go to learnpython.org.
That’s a good suggestion if you’re not sure where to start – but you can use anything. What sounds fun, or what are you trying to learn? For several years, I was interested in how far I could get through the very tricky later puzzles – so I stuck to the language I know best and put my effort into learning lots of new techniques. There’s plenty of “oh no I need some maths I’ve never looked into” and other twists to keep you busy.
But it’s also a great way to learn a new language if you’d like an excuse to try one out. I can’t stress this enough: you don’t have to aim to finish this, and there’s no time limit. Do as many of the puzzles as you like, in whatever timeframe you like. Decide what you’d like to get out of this, and be prepared to ditch it any time it’s not feeling fun or interesting any more. You can learn a lot from doing any amount of this, and it’s not meant to be a slog.
For me, personally:
- I started in 2020, using Python that I knew well and seeing how far I could get with that
- Carried on the next few years, for as long as it was fun, with an aim of “beating last year’s total”
- Last year, I definitely didn’t have time to finish things by 25th December – but I was still having fun, and kept coming back to it until, amazingly, I completed all 50 stars sometime in February
- For some extra, non-Festive learning, I started some old 2015 puzzles in Python, then redid them in a language I’m brand new to (TypeScript). This was incredibly useful, I could look at “what would I write if I knew the language” and ask “so how do I do that in TypeScript?” (for example: generator expressions!)
Things I’ve learned from past years
On to some examples of things I’ve absolutely loved learning and trying out in the last few Advents of Code.
Depth first search, and graph / pathfinding algorithms in general
A few different puzzles have some variant of “what’s the best path through this maze” – not always stated that way, but if you recognise that what they’re asking can be thought of as a maze, graph or heatmap then it prompts you to look into various already-solved and quite simple algorithms.
This kind of thing amazes me. In one puzzle, for part 1 my code just explored every possible path, then compared them all to find the shortest. Part 2’s twist was a much bigger grid, and suddenly my code was just running and running – I think my computer might have run out of memory before it explored everything. Was there a shortcut?
I found the Depth First Search algorithm described on Wikipedia. The pseudocode describing it is 5 lines of code. I thought “I can see what that’s doing … it looks a bit faster than my thing, will it make much difference?” I used the pseudocode description to write a very short function – and WOW it found the answer in about 5 seconds. It was really eye-opening. This algorithm was invented in the 1800s.
Once you’re looking out for such things, there’s all kinds of genius but straightforward to implement algorithms out there. This isn’t just useful for advent puzzles – keep an eye out for “could this be described as this kind of problem” in all kinds of code, you may be able to apply something. There’s lots of nice overviews of algorithms and their applications, like this one: Applications of the 20 Most Popular Graph Algorithms.
I’ve written a bit more about pathfinding algorithms here: Pathfinding, starring Shakey the robot.
Where to use regular expressions, and where not to
Regular expressions are a powerful tool to learn – they can be used in lots of ways to do text manipulation and pattern matching with very few lines of code. But they’re famously hard to read, and the difference between “this is a problem that a short regex can solve elegantly” and “this is not at all a job for regex, and trying to make it work will tie me in knots” is a difficult thing to spot.
Advent of Code has given me lots of chances to think “should I use regex here?”, learn more about the fantastic things they can do, and get more confident in spotting where they’re just the wrong tool for the job. I shared my thoughts on Mastodon:
I’m following another of my usual patterns with #AdventOfCode: today I thought regex might be a good tool for a bit of this puzzle, was nervous about it but it went absolutely fine, easy short readable code.
This will lead to me getting overconfident with regex and trying to use it in some horrible complicated way around day 12, leading to hours of tearing my hair out
How to use no-code aids when appropriate
In one puzzle, the input was a flat grid in the shape of a cube net, and I was having an awful time trying to code rules for how to wrap coordinates as things moved off one edge – which face would they pop onto? I was very pleased with my no-code solution to help me work it out.
All kinds of useful Python libraries
A whole range of them! Like NumPy, which I have used for work years ago but had completely forgotten – for working with matrices and various mathematical operations, it makes code so short and readable and also amazingly fast even on large datasets. This is a great tool to be able to reach for in lots of real-life code situations, as well as in contrived puzzle scenarios.
Other finds were built in to Python’s standard library. For example, have you heard of “memoization”? When a function’s quite complicated to calculate, and should give the same answer each time it’s called with the same arguments, you can get it to cache its results. If you’re calling the function a lot (and your program’s taking a long time), you might save a lot of time by using this idea, so it can just return cached values and cut out a lot of recalculation.
I had no idea that I could use the standard functools
to let me just put an @cache
decorator on any function, which is all you need to set up this kind of caching; a quick and readable way to explore whether this helps. There’s lots of adjustments you can make too: see the documentation.
Last mention: I cannot believe it was 3 years of doing Advent of Code in Python before I discovered the tqdm
module that easily gives all kinds of lovely progress bars. Instead of wondering if my code’s going to run forever, I can now see just how much trouble I’m in.
One meaning of the tqdm
initials is a Spanish phrase meaning “I love you too much” – perfect name for it, this is brilliant. Read all about it.
Maximising the work not done
In lots of the later, trickier challenges, I find myself wondering if my code will ever finish – there’s just too many loops, or too much memory usage. One “thinking out loud” post led me to a real breakthrough.
Overwhelming advice was to not stop and read a book … I sort-of listened! Instead of a whole book, I read just one chapter of Michael Abrash’s Graphics Programming Black Book (recommended in this StackOverflow answer), implemented a few of its suggestions, and took the run time down from 20 minutes down to 12 seconds. I was delighted.
I went on to read lots of that book, it’s from when Quake and other amazing 3D games were getting written for 33 MHz Pentium processors. There’s so much good advice for tackling any problem, starting with “the best optimizer is between your ears”. If you jump too early to the most efficient code, or on into assembler, you’ll find yourself with hard-to-reason-about code and lots of the big opportunities for improving the speed will be lost to you.
The chapter I started with was 17, about optimizing Conway’s Game of Life. This walks through really clearly how to understand the problem you’ve actually been asked to solve, rather than sticking with a solution you first thought of. There’s a range of creative ways to do the least work, and still find the answers you’re looking for. Like lots of the examples in this post, I took away a lot of new ideas that are useful far beyond a once-a-year coding challenge.
And that’s enough
I could probably write a lot more about my thoughts on Advent of Code …. but I think this is enough to get my point across. If you’re interested, sign up, set up somewhere you can write code, and have fun.