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…
Reference in new issue