advent of code 2023

This commit is contained in:
Wouter Groeneveld 2023-12-18 10:37:22 +01:00
parent 282515e28c
commit 1c05d33f06
1 changed files with 57 additions and 0 deletions

View File

@ -0,0 +1,57 @@
---
title: "What I Learned From Advent of Code 2023"
date: 2023-12-18T10:01:00+01:00
categories:
- programming
tags:
- programming langauges
- advent of code
---
I gave up after yesterdays' quirky A* assignment. [Advent of Code](https://adventofcode.com/) is an Advent calendar for programmers containing daily puzzle challenges in two parts. It was fun while it lasted, but my tight time constraints just can't deal with the increasing challenge as the calendar draws near Christmas Eve. I get stressed out if I miss a daily challenge: the thought of having to do two---or possibly, even more---in one day scares me. This, and the A* assignment that had me go round in circles for too long, just made me say _fuck it_.
As I approached the challenges, I wondered whether or not this was also a good opportunity to learn a new scripting language. I guess the answer again depends on the amount of daily free time you have. In my case, fighting with syntax and not knowing the definitive eloquent way to approach something in an ecosystem that is relatively new to me just took too much time. After trying out Ruby a few times, I reverted back to JavaScript, as the assignments themselves were already challenging enough. For the curious, [my code repository is public](https://git.brainbaking.com/wgroeneveld/adventofcode).
Quickly trying out syntax in the developer pane of a browser, such as `[...new Set([1, 1], [1, 2], [1, 1])]`, turned out to be key to a speedy victory. Like I mentioned in the [my ideal scripting language](/post/2023/12/my-ideal-scripting-language/) post, quick evaluation and _hackability_ are important feats to have if you want to get something done in a timely manner. You can't abuse `Set` to filter out similar arrays, by the way, but you can chat by `.toString()`-ing them. I cut a lot of corners to save time---as long as my unit test that verifies the example given in the assignment proved my algorithm worked, I didn't care.
Each Advent of Code assignment comes with two parts: part I is publicly available, and for part II, you have to create an account and sign in. Suffice to say, I skipped part II. Part II is usually the difficult part, where instead of input ranges in the hundreds, you're suddenly dealing with millions, meaning your brute force implementation will likely not work. However, if you only have a few hours a day (if that) to fiddle with a code assignment, and you also want to do this the Test First way, there's simply not enough time to do so.
After the first week, I realized I needed more tests than just the example verification. For example, on day 11, you're given a 2D map of the galaxy, with `#`s that mark a planet and `.`s marking empty spaces, like so:
```
...#......
.......#..
#.........
..........
......#...
.#........
.........#
..........
.......#..
#...#.....
```
The question is: what is the sum of the shortest paths between all the galaxies? Yet there's a twist: for each empty row and column (all filled in with `.`), the galaxy _expands_, and doubles in size to account for the years it takes for the light to reach the observatory. That means you'll have to (1) expand the galaxy and then (2) calculate the shortest paths. Instead of exposing a `solve(input)` and testing that, as I my approach was up to that day, I exposed both `expandGalaxy()` and `solve()`, meaning I can also unit test the first part of the assignment, and only then move on to the second part. This helped a lot in saving time chasing stupid bugs. The above galaxy map looks like this after expanding:
```
....#........
.........#...
#............
.............
.............
........#....
.#...........
............#
.............
.............
.........#...
#....#.......
```
Of course, part II comes along to ruin things: instead of doubling in size, it explodes and gets multiplied by a million. That means you can't simply redraw the map. Luckily, the solution is fairly simple: while calculating the shortest path, if it's in a part that gets expanded, just multiply the numbers. I---again---spent too much time getting the tests working for the first part, approaching things too visually.
It is interesting to check out others' approaches to the daily challenges. On Mastodon, there's the `#adventofcode` hashtag where people occasionally share blog posts explaining their solution, like [Tipa's galaxy expanding Python implementation](https://chasingdings.com/2023/12/11/advent-of-code-day-11-cosmic-expansion/) that had me laugh at my own approach. I started Advent of Code together with a friend [that uses Elixir's LiveBook](https://github.com/linusdm/advent_of_code_2023/tree/main) to solve the assignments. Elixir's functional and `|>` chaining nature gives for an interesting comparison with my JS implementation.
For me, the best part of Advent of Code was discussing the daily challenges and my approach with others. I learned more by checking out others' code than by writing my own. But then my friend went on a short holiday trip and fell behind. And yesterday I learned that another friend said _fuck it_ long before I did. We both want our code to work and can't put it down as long as the tests aren't green. That's great until it starts to feel like yet another stressful TODO item.
Advent of Code feels like an elimination race. A daily endurance run that, given all other things going on in life right now, I just can't keep up with. And that's okay. Next year I'll approach things differently. I won't care if I don't have the solution that same day, and I'll approach things more slower just to learn the syntax of another language. Perhaps I'll simply gather the assignments and do them in January and later, on my own pace.