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

## Part A

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

• `cpy x y` copies x (either an integer or the value of a register) into register y.
• `inc x` increases the value of register x by one.
• `dec x` decreases the value of register x by one.
• `jnz x y` jumps to an instruction y away (positive means forward; negative means backward), but only if x is not zero.

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.