DEV Community 👩‍💻👨‍💻

Cover image for Leonardo's Monorail
Robert Mion
Robert Mion

Posted on

Leonardo's Monorail

Advent of Code 2016 Day 12

Part 1

  1. Thank goodness: no reliance on Day 11
  2. Assembly code: Round...?
  3. Writing my working algorithm

Thank goodness: no reliance on Day 11

  • I failed to solve any parts of Day 11
  • That worried me coming in to Day 12

Thankfully, Day 12 is yet another...

Assembly code: Round...?

  • I'm probably remembering incorrectly, but it seems like every year - except 2021 - featured at least one assembly-code-themed puzzle

This feels like an easier one:

  • store and update numbers in registers
  • jump conditionally
  • end when a pointer is out of bounds
  • return the value stored in a particular register

I'm off to write the same algorithm for what feels like the third or fourth time...

Writing my working algorithm

Extracting each line's opcodes and operands:

Split the input at each newline character into an array of strings

For each string
  Split the string at each space character into an array of two or three strings, saved as op, x and y
  If y contains a value (meaning there were three strings)
    Construct a three-element array containing the opcode string, and either a string or number for x and y
  Else, if y is empty (meaning there were two strings)
    Construct a two-element array containing the opcode string, and either a string or number for x
Enter fullscreen mode Exit fullscreen mode

This is the JavaScript I wrote:

input.split('\n').map(line => {
  let [op, x, y] = line.split(' ')
  if (y) {
    return [op, isNaN(x) ? x : +x, isNaN(y) ? y : +y]
  } else {
    return [op, isNaN(x) ? x : +x]
  }
})
Enter fullscreen mode Exit fullscreen mode

More setup:

Set pointer to 0 so it starts reading at the first instruction
Set registers as an object with four keys, a-d, each with 0 as a value
Enter fullscreen mode Exit fullscreen mode

The dictionary of opcode functions:

cpy(x,y) {
  registers[y] = (typeof x == 'string') ? registers[x] : x;
  pointer++
},
inc(x) {
  registers[x]++
  pointer++
},
dec(x) {
  registers[x]--
  pointer++
},
jnz(x,y) {
  registers[x] !== 0 ? pointer += y : pointer++
}
Enter fullscreen mode Exit fullscreen mode

The main loop:

Do as long as pointer contains a number that could refer to an index within the bounds of the list of instructions
  Invoke the appropriate function in the dictionary of opcodes, passing as arguments the second value in the instruction and the third...even if there is no third value
Enter fullscreen mode Exit fullscreen mode
while (pointer >= 0 && pointer < rules.length) {
  opcodes[rules[pointer][0]](
    rules[pointer][1], rules[pointer][2]
  )
}
Enter fullscreen mode Exit fullscreen mode

Two mistakes I made while writing the code above:

  • I forgot to increment pointer in the three non-jnz functions
  • I wrote rules[pointer[1]] instead of rules[pointer][1], confusing the program into expecting some property 1 to exist on the number stored in pointer

After correcting those errors, the program ran and generated the correct answer as expected!

Part 2

  1. Let me guess...a performance test?
  2. Thankfully, it finishes in a few seconds

Let me guess...a performance test?

  • It seems like a simple task: change c to start as 1, then re-run
  • In prior puzzles, changing a register's starting value caused the program to run exponentially longer...seemingly forever!
  • Will that be the case here?

Thankfully, it finishes in a few seconds

  • Seven seconds, to be exact - not great
  • register a contains a number over 9 million - in Part 1 it ended containing a number just over 300 thousand
  • I don't care enough to inspect what causes the long runtime - I tried doing that in prior puzzles and it never helped me solve the puzzle
  • I'm just glad it finished in under a minute and generated the correct answer!

I did it!!

  • I solved both parts!
  • I sadly stumbled over the same mistakes I made in previous attempts: array look-up and pointer incrementing!
  • I feel prepared to attempt Part 1 of Day 23!

After solving today's puzzle and returning to the main map, I was delighted to see this animation playing:
Monorail ASCII animation

Top comments (0)

🌚 Browsing with dark mode makes you a better developer.

It's a scientific fact.