Advent of Code 2016, Day 12: Leonardo's Monorail

#ruby #advent of code 2016

Part A

On Day 12 we can implement virtual machine executing assembunny code. Our virtual machine can execute only four instructions:

It also has four registers a, b, c and d, all of them initialized with value 0. Our input is a program that looks like this:

cpy 41 a
inc a
inc a
dec a
jnz a 2
dec a

Our task is to return the value of register a after executing such program.

Here is my solution:

data = File.readlines("12.txt", chomp: true).map(&:strip)

registers = { "a" => 0, "b" => 0, "c" => 0, "d" => 0 }
pc = 0

def render(data, pc, registers)
  $stdout.clear_screen
  data.each_with_index do |line, index|
    puts [index == pc ? "=> " : "   ", index.to_s.rjust(2), line].join(" ")
  end
  puts "A = #{registers["a"]}, B = #{registers["b"]}, C = #{registers["c"]}, D = #{registers["d"]}, PC = #{pc}"
end

while pc < data.size
  line = data[pc]
  jump = false

  if line =~ /cpy (-?\d+) ([a-d])/
    value = Regexp.last_match[1].to_i
    register = Regexp.last_match[2]

    registers[register] = value
  elsif line =~ /cpy ([a-d]) ([a-d])/
    source_register = Regexp.last_match[1]
    target_register = Regexp.last_match[2]

    registers[target_register] = registers[source_register]
  elsif line =~ /inc ([a-d])/
    register = Regexp.last_match[1]
    registers[register] += 1
  elsif line =~ /dec ([a-d])/
    register = Regexp.last_match[1]
    registers[register] -= 1
  elsif line =~ /jnz (-?\d+) (-?\d+)/
    value = Regexp.last_match[1].to_i
    offset = Regexp.last_match[2].to_i

    if value != 0
      pc += offset
      jump = true
    end
  elsif line =~ /jnz ([a-d]) (-?\d+)/
    register = Regexp.last_match[1]
    offset = Regexp.last_match[2].to_i

    if registers[register] != 0
      pc += offset
      jump = true
    end
  end

  pc += 1 unless jump
end

puts registers.inspect

There is nothing fancy here. I have @registers hash that keeps track of register values, @pc which is program counter pointing to the current line of code. Then there is a loop executing each instruction of our program.

Part B

Nothing new here, the only change is that register c is initialized with value 1. It takes a lot more to execute this code then.