93 lines
1.6 KiB
Ruby
93 lines
1.6 KiB
Ruby
class Computer
|
|
attr_reader :data
|
|
def initialize(data)
|
|
@data = data
|
|
@program_counter = 0
|
|
@halted = true
|
|
end
|
|
|
|
def run
|
|
@halted = false
|
|
while !@halted
|
|
instruction_range = data[@program_counter..(@program_counter + 3)]
|
|
opcode = OpCode.for(self, *instruction_range)
|
|
opcode.execute
|
|
@program_counter += 4
|
|
end
|
|
end
|
|
|
|
def read(index)
|
|
data[index]
|
|
end
|
|
|
|
def write(index, value)
|
|
data[index] = value
|
|
end
|
|
|
|
def halt
|
|
@halted = true
|
|
end
|
|
|
|
def self.from_string(string)
|
|
new(string.split(",").map(&:to_i))
|
|
end
|
|
|
|
def self.from_file(file_path)
|
|
from_string(File.read file_path)
|
|
end
|
|
end
|
|
|
|
class OpCode
|
|
attr_reader :computer
|
|
def initialize(computer)
|
|
@computer = computer
|
|
end
|
|
|
|
def self.for(computer, *args)
|
|
case args[0]
|
|
when 1
|
|
OpCode1.new(computer, *args[1..])
|
|
when 2
|
|
OpCode2.new(computer, *args[1..])
|
|
when 99
|
|
OpCode99.new(computer)
|
|
end
|
|
end
|
|
end
|
|
|
|
class OpCode1 < OpCode
|
|
attr_reader :destination, :first_position, :second_position
|
|
def initialize(computer, arg1, arg2, arg3)
|
|
super(computer)
|
|
@first_position = arg1
|
|
@second_position = arg2
|
|
@destination = arg3
|
|
end
|
|
|
|
def value_to_write
|
|
computer.read(first_position) + computer.read(second_position)
|
|
end
|
|
|
|
def execute
|
|
computer.write destination, value_to_write
|
|
end
|
|
end
|
|
|
|
class OpCode2 < OpCode1
|
|
def value_to_write
|
|
computer.read(first_position) * computer.read(second_position)
|
|
end
|
|
end
|
|
|
|
class OpCode99 < OpCode
|
|
def execute
|
|
computer.halt
|
|
end
|
|
end
|
|
|
|
c = Computer.from_file("../data/2019/2/input.txt")
|
|
c.write(1, 12)
|
|
c.write(2, 2)
|
|
c.run
|
|
puts "Part 1: #{c.read(0)}"
|