What I've learned from the Advent of Code so far (days 1-5)

minna_xd

Minna N.

Posted on December 6, 2020

What I've learned from the Advent of Code so far (days 1-5)

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
Enter fullscreen mode Exit fullscreen mode

For example:

1-3 a: abcde
1-3 b: cdefg
2-9 c: ccccccccc
Enter fullscreen mode Exit fullscreen mode

One line contains a password policy and a password, so first I separated the policy from the password

const [policy, password] = line.split(': ');
Enter fullscreen mode Exit fullscreen mode

Then I separated the numbers from the character in the policy:

const [amount, character] = policy.split(' ');
Enter fullscreen mode Exit fullscreen mode

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('-');
Enter fullscreen mode Exit fullscreen mode

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'];
Enter fullscreen mode Exit fullscreen mode

I got a tip to make it sooo much more elegant:

let validChars = Array.from('0123456789abcdef');
Enter fullscreen mode Exit fullscreen mode

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' ) { ... }
Enter fullscreen mode Exit fullscreen mode

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) { ... }
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

Compare with

let currentChar = colourArray[i];

if (validChars.indexOf(currentChar) === -1) {
  return false;
}
Enter fullscreen mode Exit fullscreen mode

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

💖 💪 🙅 🚩
minna_xd
Minna N.

Posted on December 6, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Wait For It
adventofcode Wait For It

December 11, 2023

If You Give A Seed A Fertilizer
adventofcode If You Give A Seed A Fertilizer

December 8, 2023

Trebuchet?!
adventofcode Trebuchet?!

December 1, 2023

Scratchcards
adventofcode Scratchcards

December 6, 2023