Every year I embark on a magical Christmas adventure with Advent of Code. Quite often, I end up working on the first few days' challenges and then it takes a backseat to other things in life. This year – like every other before it – I'm serious though and want to try to finish the entire challenge and document my learnings meanwhile.
This series won't be a tutorial nor a "this is how you solve these challenges" guide but rather a journal of my progress with Advent of Code and Rust. If you're afraid of being spoiled on those challenges, try to solve them first before reading further as I'll show and talk about some code as well.
Why am I so excited about code puzzles?
When I was a kid, a chocolate advent calendar was the best way to get hyped for Christmas. Every morning, I started the day by opening a new window and find chocolate that was usually very sub-par in quality but it was never about the taste of chocolate. It was about the freedom to eat chocolate in the morning and the excitement of days leading towards the Christmas Eve (which is when we Finns celebrate).
As a web developer occasionally working on client projects but mostly focusing on developer community building, I'm often looking to do something fun with code, experimenting with new technologies and keep learning but I don't want to start a multi-year project. Advent of Code is perfect for that. I can do snack-sized puzzles with some technology without any pressure of finishing or writing amazing code.
This year I'm using Rust
I have never really done any systems programming. I did one combined C & C++ course in university but that's pretty much it. Last year, when I was speaking at PyCon Estonia, I met Dom Weldon and saw his talk Oxidizing MyPy in which he talked about using Rust and Python together. That sparked an interest in me to get started with Rust.
It took me a year to actually do anything with it. I was kinda saving Rust for another project but since I realized I might never make that happen, I'll start learning Rust with Advent of Code.
One of the reasons I wanna learn Rust is to build command line tools. I have previously written about my love for CLI tools if you wanna know why. I've seen Rust becoming quite popular for CLI tools and I want to get into that groove.
Days 0 to 1
First contact with Rust
I wanted to get a good start with a new technology so I took a head start and spent the evening of Nov 30th to make sure I had a setup where I can start working on.
So I started by installing Rust and Cargo, read the first few chapters of Rust docs, built the number guessing game in the documentation to make sure I know the very basics and built a template for unit tests.
For me, Advent of Code is perfect place to use Test-Driven Development and I've figured that if I learn how to write and run tests with new technology from the very first touchpoint, it's more likely I'll write good tests when I start using the language in more serious projects.
Another thing I wanted to learn is the conventions of documentation in Rust. And Rust is great for that. Already on Day 0, I fell in love with cargo doc
that generates local documentation, not only from your own code but of your dependencies as well. How is that not a main feature in all languages and ecosystems? It is so smart. And it encourages good documentation of your own crates and functions as well. Rustdoc has great documentation for how to write and build documentation.
December 1st
First interesting thing I noticed with Rust is that it's recommended to keep unit tests in the same files as the functionality. Rust uses something called conditional compilation which means that you can define in source level, if you want something to be compiled to the final binary or in this case, only when running tests. That can be defined by annotating a function with #[cfg(test)]
.
A bit similar functionality that I've used before is Python's doctest that allows tests to be included in docstrings of functions. Rust also has similar functionality but from a different perspective. Developers are encouraged to add an example or two into their documentation of functions so it's easier for readers to use the functionality. To make sure those documentation examples work, rustdoc runs those examples and tests them for you. What a great way to keep documentation and code in sync.
And then it happened. I wrote my very first Rust code (by furiously googling and copy-pasting code together) and IT WORKED. I got my very first star for this year. My code didn't look very beautiful and it probably wasn't the most idiomatic Rust. I'm guessing it looks like Python or Javascript developer's first Rust code.
So I submitted it for code review to my colleagues at Futurice and fellow Rust developers at Koodiklinikka. A great way to improve fast is to take a challenge, figure it out by reading docs and googling and then having a discussion about it with other developers. Thanks especially to Aarni and Jaakko for helping me improve my first bits of code.
Learning new is exhausting
I've been coding more or less actively for a few decades since my teenage years. I noticed something very interesting (which reminded me it's been a while since I've been actively learning something new): even though I'm very familiar with basic concepts like reading input and looping and all that, when learning a new language like Rust, I keep completely forgetting all the basics.
I decided to build my solution so that it reads the result from standard input rather than file and Jaakko did the opposite. After discussing our solutions and reviewing our code, I totally forgot I had done that, ran my code and waited for half a minute wondering why my code is so slow. I had forgotten to provide the input into standard input so the code wasn't doing anything.
On the bright side, I love that kind of really intensive learning. It tickles my brain in just the right way and gets me excited with stuff.
The first couple of days of Advent of Code are usually quite nice warmup challenges. They are helpful in making sure my setup works and my code is run correctly. This year was not an exception to that rule and I'm happy about that because there's always an extra added layer of complexity when setting new things up.
My solutions
I update my solutions to my GitHub repository at hamatti/adventofcode-2020. Since I'm a very beginner with Rust, I don't recommend taking them as example or you'll probably learn some bad habits.
I won't probably solve those challenges every day but rather in batches of a few days at the time.