Advent of Code

Category : personal


The Advent of Code is a fun little challenge I like to participate in when I have time. It always runs from December 1st until Christmas Day, providing you with two puzzles per day. You’re allowed to use any language or framework you want, but you cannot solve the puzzles by hand, due to the sheer size of the puzzle input. Each pair of puzzles requires a certain technique, for example some kind of pathfinding algorithm. You can often get away with using some kind of brute-force technique on the first puzzle. But then for the second one, they might for example ask you to run a billion iterations, forcing you to really find a proper solution and optimise your code.

The further you get, the more time it tends to take to solve the puzzles, so sadly with December already being a very busy month, I’ve only been able to finish the whole Advent of Code once. But it’s fun to try anyway.

2021

In 2021, I wanted to focus on writing short, clean C#, and to hopefully experiment a little with some new features in the language. You can find the source code for this one on my Github

2020

Word had been going around about a new language called Rust, so I figured the Advent of Code would be a great way to try it out. You can find it on my Github

It’s a very interesting language. It’s a low-level language that can achieve the same performance and memory-efficiency as C++, but it is completely memory-safe and thread-safe, due to its ownership system in which the lifetime and ownership of variables is determined at compile-time.

Working in Rust on these puzzles was definitely interesting, because it forced me to think about my code in a different way. For example, in most languages, variables are exactly that, variable. Meaning they can change. In Rust, they’re ‘const’ by default, you need to explicitly declare them as ‘mutable’ if you want to be able to change them.

fn puzzle1(passwords:&Vec<Password>) -> u32
{
    let mut result = 0;
    for password in passwords
    {
        let count = password.pass.matches(password.req).count();
        if count >= password.min.try_into().unwrap() && count <= password.max.try_into().unwrap()
        {
            result += 1;
        }
    }

    return result;
}

2017, 2018 and 2019

For small puzzles and scripts such as these, Python is my go-to language, because it allows me to focus on the challenge itself, instead of having to think about classes and variable declaration and memory management, for example. As soon as the code gets too long however, or split into multiple files, I like to switch to a language with a stronger type system such as C#.

As a small example, here’s my solution to the second puzzle of day 10, 2017.

def round(hash, lengths, position, skip):
    for length in lengths:

        for i in range(length // 2):
            left = (position + i) % len(hash)
            right = (position + length - i - 1) % len(hash)

            temp = hash[left]
            hash[left] = hash[right]
            hash[right] = temp

        position = (position + length + skip) % len(hash)
        skip += 1

    return hash, position, skip

def solve(input):
    lengths = []
    for c in input:
        lengths.append(ord(c))

    lengths += [17, 31, 73, 47, 23]

    hash = list(range(256))
    position = 0
    skip = 0

    for i in range(64):
        hash, position, skip = round(hash, lengths, position, skip)

    result = []
    for i in range(0, len(hash), 16):
        char = 0
        for x in range(i, i + 16):
            char ^= hash[x]

        result.append(char)

    output = ""
    for i in result:
        output += "%0.2x" % i

    print(output)

solve("34,88,2,222,254,93,150,0,199,255,39,32,137,136,1,167")

The code for these three years can be found on my Github. I managed to solve all the puzzles in 2017, but sadly not in 2018 or 2019, due to time limitations.


About Vincent Booman

Hi, my name is Vincent Booman. For me, development is not about a specific language or software, it's about what kind of impact they enable.

Follow @Feathora