What I've learned from the Advent of Code so far (days 1-5)
Minna N.
Posted on December 6, 2020
I consider myself an advanced beginner in programming. I lack a lot of knowledge in best practices, gotchas, elegance... let alone algorithms, optimizations... I have no clue.
I'm quite sure I won't make it through Advent of Code but I wanted to give it a go anyway. I first thought to use Java to solve the puzzles because I'm more comfortable processing line-by-line input and doing "tricks" with it (I did a comprehensive course on it just at the beginning of this year), but decided on JavaScript because it's more beneficial for the things I'm learning at the moment.
On the first five days, I had a couple of facepalm moments 🤦 but also some proud moments 🏆.
Here are some of the things that have helped me on puzzle-solving days 1-5.
Neat feature: Destructuring
On day 2 I was quite proud of myself for remembering the destructuring assignment feature. The task is to process a list with the following data:
int-int char: string
For example:
1-3 a: abcde
1-3 b: cdefg
2-9 c: ccccccccc
One line contains a password policy and a password, so first I separated the policy from the password
const [policy, password] = line.split(': ');
Then I separated the numbers from the character in the policy:
const [amount, character] = policy.split(' ');
And finally the first number and the second number (representing min and max values in the first part of the puzzle and two positions in the second part):
const [min, max] = amount.split('-');
Very handy!
Neat method: Array.from()
For the colour code validation on day 4, I use indexOf()
. First I had an array with the possible values like so:
let validChars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
I got a tip to make it sooo much more elegant:
let validChars = Array.from('0123456789abcdef');
Coolio! 😎 As it sounds like, here Array.from()
creates an array from the given string.
If you are wondering why I'm processing the numbers as strings, it's just so much simpler because the valid characters are either numbers or strings. And actually, the value comes as a string to validation so ===
works more reliably this way.
I'm really digging this array of valid values, too. First I had
if (value === 'amb' ||
value === 'blu' ||
value === 'brn' ||
value === 'gry' ||
value === 'grn' ||
value === 'hzl' ||
value === 'oth' ) { ... }
for the hair colour validation 😅 but I just changed it to
let validColors = ['amb', 'blu', 'brn', 'gry', 'grn', 'hzl', 'oth'];
if (validColors.indexOf(value) != -1) { ... }
Tip: Break up processing into functions
On day 4 you have to do data validation and I was puzzled by how I'd be able to end processing of an invalid value in a nested loop and get back to the outer loop to validate the next value. I got a tip – one that I should remember by now – that I should make more helper functions. There's no such thing as too many functions (within reason). 😄
My colour code validation was made much simpler with a helper function that returns either true or false.
function hexValidity(hexValue) {
let validChars = Array.from('0123456789abcdef');
let colourArray = Array.from(hexValue);
if (colourArray[0] != '#' || colourArray.length != 7) {
return false;
}
for (let i = 1; i < colourArray.length; i++) {
let currentChar = colourArray[i];
if (validChars.indexOf(currentChar) === -1) {
return false;
}
}
return true;
}
Tip: Create variables more often
The code is easier to read when you first assign results of functions, values from arrays, etc. in variables and use them in another structure. For example in my colour validation code for day 4, I first had:
if (validChars.indexOf(colourArray[i]) === -1) {
return false;
}
Compare with
let currentChar = colourArray[i];
if (validChars.indexOf(currentChar) === -1) {
return false;
}
Tip: Use modulo where you can
I keep forgetting how useful (and multi-use) modulo %
is.
For my toboggan trajectory on day 3, I skip to the beginning of the line ("horizontal index" 0) when I go over the length of the array (31) so in my code, I subtract the length from the horizontal index if it's over 30 (last possible index). With modulo, I could just use index % 31
and be done with it.
If you have a situation where a value has to loop back to 0 at some point, use modulo.
Best practice: Early exit
It's best to start by validating your data so you can break out of a loop/function as early as possible. For example on day 4, it's wise to check if the passport ID even has the required 9 characters before you start validating if each of the characters is a digit. Same with the hex colour codes: if it doesn't have a hash #
at the beginning and exactly 6 characters after it, there's no point validating it in more detail.
Take heed: Scope of variables
This was a moment of a huge facepalm. On day 4 you have to do data validation, which in itself is quite complicated to do for seven different value types.
After I'd extracted the value validation itself into a separate function, as mentioned above, I found myself facing an infinite loop. The code was able to process the first three values ok but then it got stuck looping with second and third value. A lot of debugging later, I was this much wiser: 💡 remember to always declare the initial variable of a for
loop 💡 or the code may end up using a completely wrong variable.
I had forgotten the let
from a couple of for
loops where used i
as the index counter. 🤦
This actually brings to mind another tip for myself: keep in mind the existence of for/of
loop! I could've made my code a lot simpler with it.
A proud moment on day 3
First I was completely at a loss with the puzzle on day 3: how am I supposed to figure out a trajectory through lines of data? I don't know about vectors or any map algorithms.
I started visualizing the problem as a matrix, but then was unsure how that would be done in JavaScript (would've been easy-peasy in Java) but it got me a step further: I put the lines into an array (array item per line) for vertical movement and used charAt
for the horizontal dimension of my "matrix". Once I had my function for the part 1 working and I was looking at part 2, I first thought "oh no, the function is going to be so messy with the for loop times 5". But then I realized, if I refactor my first function a bit I can reuse it by giving the numbers for traversing (x steps right, y steps down) as parameters and just assign the results to variables. 🏆
Cover photo by Markus Spiske on Unsplash
Posted on December 6, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.