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
class Computer < Struct.new(:instructions)
  INSTRUCTIONS = {
    hlf: ->(c,r) { c.registers[r] /= 2; c.pc += 1 },
    tpl: ->(c,r) { c.registers[r] *= 3; c.pc += 1 },
    inc: ->(c,r) { c.registers[r] += 1; c.pc += 1 },
    jmp: ->(c,o) { c.pc += o.to_i },
    jie: ->(c,r,o) { c.pc += (c.registers[r].even?) ? o.to_i : 1 },
    jio: ->(c,r,o) { c.pc += (c.registers[r] == 1) ? o.to_i : 1 },
  }

  attr_reader :registers
  attr_accessor :pc

  def initialize(*)
    super

    @registers = Hash.new(0)
    @pc = 0
  end

  def run!
    loop do
      instruction, *args = self.instructions[self.pc]
      break if instruction.nil?

      INSTRUCTIONS[instruction.to_sym].call(self, *args)
    end
  end
end

instructions = DATA.read.split("\n").map {|line| line.split(/,? /) }

c = Computer.new(instructions)
c.registers[?a] = 1
c.run!
p c.registers

__END__