[2019][ruby][2.x] refactor a computer class out of day 2

sorbet
Alpha Chen 5 years ago
parent 4179982a82
commit 475ad99996

@ -0,0 +1,63 @@
OPCODES = {
1 => ->(m, a, b, c) { m[c] = m[a] + m[b] },
2 => ->(m, a, b, c) { m[c] = m[a] * m[b] },
99 => ->(*) { throw :halt },
}
class Computer
def self.from(input)
new(input.split(?,).map(&:to_i))
end
def initialize(program)
@memory = program
@pc = 0
end
def run
each.inject(nil) {|_,i| i }
end
def each
return enum_for(__method__) unless block_given?
catch(:halt) do
loop do
opcode = OPCODES.fetch(@memory.fetch(@pc))
@pc += 1
n = opcode.arity - 1
args = (0...n).map {|i| @memory.fetch(@pc + i) }
@pc += n
opcode.call(@memory, *args)
yield @memory
end
end
end
end
require "minitest"
class TestComputer < Minitest::Test
def test_samples
c = Computer.from("1,9,10,3,2,3,11,0,99,30,40,50").each
assert_equal 70, c.next.fetch(3)
assert_equal 3500, c.next.fetch(0)
end
def test_more_samples
run = ->(p) { Computer.from(p).run }
assert_equal 2, run.call("1,0,0,0,99").fetch(0)
assert_equal 6, run.call("2,3,0,3,99").fetch(3)
assert_equal 9801, run.call("2,4,4,5,99,0").fetch(5)
assert_equal 30, run.call("1,1,1,4,99,5,6,0,99").fetch(0)
end
end
if __FILE__ == $0
require "minitest/autorun"
end

@ -1,47 +1,20 @@
OPCODES = ARGF.read.split(?,).map(&:to_i) require_relative "computer"
# opcodes[1] = 12 program = ARGF.read.split(?,).map(&:to_i)
# opcodes[2] = 2
# pc = 0 # modified = program.dup
# loop do # modified[1] = 12
# p opcodes # modified[2] = 2
# case opcodes[pc] # c = Computer.new(modified)
# when 1 # puts c.each.inject(nil) {|_,i| i }.fetch(0)
# opcodes[opcodes[pc+3]] = opcodes[opcodes[pc+1]] + opcodes[opcodes[pc+2]]
# pc += 4
# when 2
# opcodes[opcodes[pc+3]] = opcodes[opcodes[pc+1]] * opcodes[opcodes[pc+2]]
# pc += 4
# when 99
# puts opcodes[0]
# exit
# end
# end
def run(noun, verb) noun, verb = (0..99).flat_map {|noun| (0..99).map {|verb| [noun, verb] } }
memory = OPCODES.dup .find {|(noun, verb)|
memory[1] = noun modified = program.dup
memory[2] = verb modified[1] = noun
modified[2] = verb
pc = 0 c = Computer.new(modified)
loop do final = c.run
case memory[pc] final.fetch(0) == 19690720
when 1 }
memory[memory[pc+3]] = memory[memory[pc+1]] + memory[memory[pc+2]] puts 100 * noun + verb
pc += 4
when 2
memory[memory[pc+3]] = memory[memory[pc+1]] * memory[memory[pc+2]]
pc += 4
when 99
return memory[0]
end
end
end
(0..99).each do |noun|
(0..99).each do |verb|
value = run(noun, verb)
puts 100 * noun + verb and exit if value == 19690720
end
end

Loading…
Cancel
Save