1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
registers = { ?a => 7, ?b => 0, ?c => 0, ?d => 0 }
pc = 0
data = DATA.each_line.map(&:chomp).to_a

while pc < data.size
  line = data[pc]
  puts "#{registers}"
  puts "#{pc}: #{line}"

  case line
  when /cpy ([a-d]|-?\d+) ([a-d])/
    value = registers.fetch($1) { $1.to_i }
    registers[$2] = value
    pc += 1
  when /inc ([a-d])/
    registers[$1] += 1
    pc += 1
  when /dec ([a-d])/
    registers[$1] -= 1
    pc += 1
  when /jnz ([a-d]|\d+) ([a-d]|-?\d+)/
    value = registers.fetch($1) { $1.to_i }
    count = registers.fetch($2) { $2.to_i }
    pc += value.zero? ? 1 : count
  when /tgl ([a-d]|-?\d+)/
    value = registers.fetch($1) { $1.to_i }
    line = data[pc + value]
    if line.nil?
      pc +=1
      next
    end

    instruction, *args = line.split(/\s+/)

    case args.size
    when 1
      instruction = (instruction == 'inc') ? 'dec' : 'inc'
    when 2
      instruction = (instruction == 'jnz') ? 'cpy' : 'jnz'
    else
      raise 'omg'
    end

    data[pc + value] = "#{instruction} #{args.join(' ')}"

    pc += 1
  else
    puts "skipping line: #{line}"
    pc += 1
  end
end

p registers

__END__