17 December 2016

Advent of Code

I've long been aware of Code Katas - programming exercises you can do as practice, to improve problem-solving and coding skills. Much like a kata in karate, they're a set of individual "moves" brought together for a fixed purpose, that you can practice with and improve on.

Only trouble is, I don't find them particularly satisfying. They're too unstructured, usually without a known answer you're trying to calculate.

Recently, I was made aware of the "Advent of Code", an annual advent calendar of daily programming challenges. I wasn't too sure how it'd be any different to Code Katas, but then I got started.

It's a lot of fun! So, how is it different to Code Katas then?

Firstly, one is released each day in December. So there's a time incentive, and your choices of what to do are limited (which is good).

Secondly, you register with the site, and for each challenge, you get your own custom input to the problem - an embarrassingly simple example would be "You need to multiply two numbers together. Your inputs are 2 and 5." You then run your code to produce the result they asked for, and enter it into the website. It's then confirmed as correct or incorrect. So, you actually have a correct answer! (Unlike most Katas, which are challenges like "Implement a shop checkout system") It's hugely satisfying reading your custom input, processing it, and providing the correct answer. And when you do, you get a star, and unlock part 2 of each challenge.

Thirdly, there's a community actively working on these challenges, making you feel like you're taking part in something bigger. Which you are.

Finally, there's a loose, silly narrative winding through each of the challenges, giving a bit more purpose to each exercise.

I decided to implement these challenges in core Java. You can see my solutions and progress on my GitHub. So far, most of them have been fairly straightforward, but I admit I am struggling with a few of them!

TDD

For bigger projects, I admit I've not used Test Driven Development all that much, but it's perfect for such challenges. You're given an example input and output, so I can test that in a unit test. I also write tests for individual parts of each implementation, so that I know that component is working as expected.

When I then run the full application against the proper input, most of the time it works perfectly. If not, it's because the input contained purposefully unexpected values, so I simply write another test for that edge case, fix the problem, and run it again.

Solution Style

A few times, when I've finished my implementation, I've gone online to see how other people have solved the solutions. There have certainly been some clever and unusual approaches! I made an interesting observation though.

While the code I've written for these challenges is certainly not production quality, it seems I naturally write code for easier maintenance and flexibility. This inherently means I'm writing more verbose code in many cases. However, when I got to the Part Two challenges, I often only needed to use what I had previously written slightly differently to get the result the challenge required.

I know that the performance and memory usage of many of my algorithms could be improved, some significantly. But at the moment, they don't need to be. They perform more than fast enough for the intended use, with the advantage that they're easier to maintain. I bet that those people who heavily optimised their Part One solutions often had an absolute nightmare modifying it for Part Two.

Further Learnings

Going on from what I said in the last paragraph, you could argue that heavily optimising the algorithms would be a good learning experience. And... you'd be right. I may well revisit some of these in the future and do just that, but for now, my aim is to implement my solutions in the most appropriate form, and not spend too long on each of them.

I also plan to reimplement some of my solutions in Ruby. I currently have limited experience writing more hardcore data processing code in that language, so it'll be invaluable for future Rails projects.

As fun as doing Advent of Code is, doing it in Java alone isn't really teaching me anything new, just flexing my problem-solving muscles. That in itself is still valuable, but I'm not spending my time just doing this - I'm still working through tutorials, example projects and personal projects in Rails and Spring technologies.

No comments:

Post a Comment