This repo stores all the Advent of Code solutions that I have written.
In its final form, I want the repo to store the complete solution to every Advent of Code problem.
Apart from that, another goal is to learn things while doing these problems. One way I've ensured that this goal will be met, to some extent at least, is by forcing myself to do each year in a different programming language. So far, the languages I've decided are
- 2015 will be in Java.
- 2018 will be in Rust. (Day 1 had to be redone because the original inputs were for a different AoC account which has since been lost to time.)
- 2022 will be in C++.
- 2023 will be in Python.
The remaining years are, as of now, undecided.
Here is the year-to-language mapping in an tabular form:
Year | Programming Language |
---|---|
2015 | |
2016 | ??? |
2017 | ??? |
2018 | |
2019 | ??? |
2020 | ??? |
2021 | ??? |
2022 | |
2023 | |
2024 | |
2025 | TBA |
The years with "???" means they have not been decided yet, and no progress has been made in those years yet. "TBA" means "To Be Announced", and it will be announced when the Advent of Code for that year starts.
In order to be able to easily see the progress that I have made so far, I added a few banners below, which show the progress that has been made according to a couple of different metrics.
The repository structure is quite simple. Assuming that advent-of-code
is the top-level directory, it has a directory for each year.
Inside each directory, there is an inputs/
directory which stores the input data for each day in .txt
format. The naming scheme that was followed was dayX.txt
, where X
is the day number. For example, the input for the 16th day is day16.txt
.
In many cases, I also added the example input they gave in the problem description to the repo in order to use it as a test run for my programs, to check for bugs. The naming scheme used for these files are simple:
- If there was only 1 test input file required, then the naming scheme is
dayX-test.txt
, - and if a separate test input file was required for each part, then the naming scheme is
dayX-partY-test.txt
,
where X
is the day number like before, and Y
is either 1
or 2
, depending on which part the test input is for.
The format for the solutions is very straightforward: Each program is named dayX_partY.ext
, where, like before, X
is the day number, Y
is the part number (so either 1
or 2
), and .ext
is the usual source file extension used for that program.
So, since I'm doing all the 2015 problems in Java, .ext
is .java
in the 2015/
directory. On the other hand, since 2023 is in Python, .ext
for 2023 is .py
.
The repo originally used hyphens as delimiters between the different parts of the program file names. I had to change the 2023 program file names to underscores, because hyphens were being interpreted as minus signs by the Python Interpreter, and this was preventing me from importing other source files as modules. For example, if I wanted to use the Part 1 scaffolding for Part 2, I was unable to do so.
For this reason, I changed all the filename delimiters to underscores over the course of four commits.
At the time of writing (this subsection), Part 1 code was used in the Part 2 solution for Day 2 and Day 6 of 2023.
Here is what the repo structure looks like, at the time of writing (this subsection):
advent-of-code/
├─ 2015/
│ ├─ inputs/
│ │ ├─ day1.txt
│ │ ⋮
│ ├─ day1_part1.java
│ ├─ day1_part2.java
⋮
├─ 2018/
│ ├─ inputs/
│ │ ├─ day1.txt
│ │ ⋮
│ ├─ day1_part1.java
│ ├─ day1_part2.java
⋮
├─ 2023/
│ ├─ inputs/
│ │ ├─ day1.txt
│ │ ⋮
│ ├─ src/
│ │ ├─ day6_part2_helper.hpp
│ │ ├─ day6_part2_helper_alt.cpp
│ │ ├─ day6_part2_helper.cpp
│ │ ⋮
│ ├─ modules/
│ │ ├─ helper.so
│ │ ├─ libday6_part2_helper.so
│ │ ⋮
│ ├─ CMakeLists.txt
│ ├─ __init__.py
│ ├─ day1_part1.py
│ ├─ day1_part2.py
⋮
│ ├─ day6_part1.py
│ ├─ day6_part2.py
⋮
There are many holes, and entire years are currently missing, but those will (hopefully) be filled in over time 🤞
Since there are multiple languages used in the repository, it makes sense to talk about the version(s) with which the code has been tested, and the version(s) with which the code was run.
Most of the Python solutions should work even with an older Python version like 3.9. That being said, the only guarantee I can give is for Python 3.11 onwards, since that is the version I used to run my Python code.
At the time of writing this subsection, the only Java code in the repository is the Day 1 Parts 1 and 2 solution for 2015. I ran the code using Java 22 Early Access. That being said, it should work on any Java version 8 onwards.
As such, there are no real MSRV
For best results, the code should be compiled for C++20 or later. All the C++ code currently in the repository works with C++20 and above, though at some point I might end up using a C++23-only construct, at which point I would have to upgrade the C++ version requirement accordingly.
One important thing to note is that the working directory is assumed to be the directory in which the program file resides. So, if we want to run 2023's Day 4 Part 2 solution, we would run python day4_part2.py
from inside the 2023/
directory.
Apart from that, the only other important things to note is that there is a CMake script to help build the C++ libraries required for the alternative 2023 Day 6 Part 2 solutions. To use those, run
cmake -S. -Bmodules
with the 2023/
as your current working directory, and then run
cmake --build modules
After that, you should be able to run python day6_part2.py
without any issues.
This section deals with certain special cases where more work was done than one would expect, or where things were done differently than one would expect. In each case, I discuss why it was required, and what exactly I did.
Originally, the 2015 Day 1 Part 1 solution was the thing which started the whole repository. However, when I was going back and checking old years on the Advent of Code website, I realized that my 2015 Day 1 was not finished. I realized then that I must have used a different account to do it.
Since I already had the code, I decided to run it on the input file that was already in the repo, which didn't work because the input is different for each user. Once I redownloaded the input, and reran the program, I got the required answer.
After reading Part 2 of Day 1, I decided it was so simple that I might as well finish it, which is why I added 2015/day1_part2.java
.
For this reason, even though the Day 1 Part 1 file was originally added in 41420bd, it had to be redone in f2be2fc.
A similar case as the one above. I redownloaded the input files and reran the programs.
For this problem, I first wrote a pure Python solution, which took around 4 seconds to run on my machine. This solution can be found in the calculate_ways
function.
4 seconds felt like an unacceptably long amount of time, especially because the problem boiled down to finding the interval for which a certain parabola is less than 0. This is a task that can be done with pen and paper relatively easily, though it would be boring and have messy calculations in this case.
My machine-friendly alternative was to create a range of numbers as a list (or array):