More intcode
This commit is contained in:
parent
b004c936f0
commit
d30e3f9600
@ -1,79 +0,0 @@
|
|||||||
class Intcode
|
|
||||||
attr_reader :memory, :pc, :stopped
|
|
||||||
def initialize(memory)
|
|
||||||
@initial_memory = memory
|
|
||||||
@memory = memory.clone
|
|
||||||
@pc = 0
|
|
||||||
@stopped = true
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.for(string)
|
|
||||||
new string.split(",").map(&:to_i)
|
|
||||||
end
|
|
||||||
|
|
||||||
def run!
|
|
||||||
@stopped = false
|
|
||||||
@pc = 0
|
|
||||||
step! until stopped
|
|
||||||
end
|
|
||||||
|
|
||||||
def reset!
|
|
||||||
@memory = @initial_memory.clone
|
|
||||||
@pc = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
def step!
|
|
||||||
case instruction
|
|
||||||
when 1
|
|
||||||
add!
|
|
||||||
when 2
|
|
||||||
multiply!
|
|
||||||
when 99
|
|
||||||
halt!
|
|
||||||
else
|
|
||||||
raise "invalid instuction #{instruction} at #{pc}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def add!
|
|
||||||
v1 = peek(peek(pc + 1))
|
|
||||||
v2 = peek(peek(pc + 2))
|
|
||||||
log "adding #{v1} and #{v2}"
|
|
||||||
poke(peek(pc + 3), v1 + v2)
|
|
||||||
@pc += 4
|
|
||||||
end
|
|
||||||
|
|
||||||
def multiply!
|
|
||||||
v1 = peek(peek(pc + 1))
|
|
||||||
v2 = peek(peek(pc + 2))
|
|
||||||
log "multiplying #{v1} and #{v2}"
|
|
||||||
poke(peek(pc + 3), v1 * v2)
|
|
||||||
@pc += 4
|
|
||||||
end
|
|
||||||
|
|
||||||
def halt!
|
|
||||||
log "halting!"
|
|
||||||
@stopped = true
|
|
||||||
end
|
|
||||||
|
|
||||||
def instruction
|
|
||||||
peek pc
|
|
||||||
end
|
|
||||||
|
|
||||||
def peek(address)
|
|
||||||
memory[address]
|
|
||||||
end
|
|
||||||
|
|
||||||
def poke(address, value)
|
|
||||||
log "poking #{value} into #{address}"
|
|
||||||
memory[address] = value
|
|
||||||
end
|
|
||||||
|
|
||||||
def log(message)
|
|
||||||
puts message if logging?
|
|
||||||
end
|
|
||||||
|
|
||||||
def logging?
|
|
||||||
false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
16
ruby/2019/5/bin/problem
Normal file
16
ruby/2019/5/bin/problem
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
require "intcode"
|
||||||
|
|
||||||
|
intcode = Intcode.for STDIN.read.chomp
|
||||||
|
intcode.input.push 1
|
||||||
|
intcode.run!
|
||||||
|
|
||||||
|
puts "Part 1: #{intcode.output.last}"
|
||||||
|
|
||||||
|
intcode.reset!
|
||||||
|
intcode.input.push 5
|
||||||
|
intcode.run!
|
||||||
|
|
||||||
|
puts "Part 2: #{intcode.output.first}"
|
||||||
|
|
||||||
155
ruby/2019/lib/intcode.rb
Normal file
155
ruby/2019/lib/intcode.rb
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
class Intcode
|
||||||
|
attr_reader :memory, :pc, :stopped, :input, :output
|
||||||
|
def initialize(memory)
|
||||||
|
@initial_memory = memory
|
||||||
|
@memory = memory.clone
|
||||||
|
@pc = 0
|
||||||
|
@stopped = true
|
||||||
|
@input = []
|
||||||
|
@output = []
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.for(string)
|
||||||
|
new string.split(",").map(&:to_i)
|
||||||
|
end
|
||||||
|
|
||||||
|
def run!
|
||||||
|
@stopped = false
|
||||||
|
@pc = 0
|
||||||
|
step! until stopped
|
||||||
|
end
|
||||||
|
|
||||||
|
def reset!
|
||||||
|
@memory = @initial_memory.clone
|
||||||
|
@pc = 0
|
||||||
|
@output = []
|
||||||
|
@input = []
|
||||||
|
end
|
||||||
|
|
||||||
|
def step!
|
||||||
|
log "pc: #{pc}, instruction: #{instruction}"
|
||||||
|
case opcode
|
||||||
|
when 1
|
||||||
|
add!
|
||||||
|
when 2
|
||||||
|
multiply!
|
||||||
|
when 3
|
||||||
|
read_input!
|
||||||
|
when 4
|
||||||
|
write_output!
|
||||||
|
when 5
|
||||||
|
jump_if_true!
|
||||||
|
when 6
|
||||||
|
jump_if_false!
|
||||||
|
when 7
|
||||||
|
less_than!
|
||||||
|
when 8
|
||||||
|
equals!
|
||||||
|
when 99
|
||||||
|
halt!
|
||||||
|
else
|
||||||
|
raise "invalid opcode #{opcode} at #{pc}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def parameters
|
||||||
|
parameter_modes.each_with_index.map do |mode, index|
|
||||||
|
case mode
|
||||||
|
when 0
|
||||||
|
peek(pc + 1 + index)
|
||||||
|
when 1
|
||||||
|
pc + 1 + index
|
||||||
|
else
|
||||||
|
raise "Invalid parameter mode #{mode}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def add!
|
||||||
|
log "adding #{peek(parameters[0])} and #{(parameters[1])}"
|
||||||
|
poke(parameters[2], peek(parameters[0]) + peek(parameters[1]))
|
||||||
|
@pc += 4
|
||||||
|
end
|
||||||
|
|
||||||
|
def multiply!
|
||||||
|
log "multiplying #{peek(parameters[0])} and #{peek(parameters[1])}"
|
||||||
|
poke(parameters[2], peek(parameters[0]) * peek(parameters[1]))
|
||||||
|
@pc += 4
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_input!
|
||||||
|
i = input.shift
|
||||||
|
log "reading input #{i} into #{parameters[0]}"
|
||||||
|
poke(parameters[0], i)
|
||||||
|
@pc += 2
|
||||||
|
end
|
||||||
|
|
||||||
|
def write_output!
|
||||||
|
o = peek(parameters[0])
|
||||||
|
log "outputting #{o} from #{parameters[0]}"
|
||||||
|
output.push o
|
||||||
|
@pc += 2
|
||||||
|
end
|
||||||
|
|
||||||
|
def jump_if_true!
|
||||||
|
predicate = peek(parameters[0])
|
||||||
|
log "jumping to #{peek(parameters[1])} if #{predicate}"
|
||||||
|
@pc = predicate > 0 ? peek(parameters[1]) : @pc + 3
|
||||||
|
end
|
||||||
|
|
||||||
|
def jump_if_false!
|
||||||
|
predicate = peek(parameters[0])
|
||||||
|
log "jumping to #{peek(parameters[1])} unless #{predicate}"
|
||||||
|
@pc = predicate == 0 ? peek(parameters[1]) : @pc + 3
|
||||||
|
end
|
||||||
|
|
||||||
|
def less_than!
|
||||||
|
lt = peek(parameters[0]) < peek(parameters[1])
|
||||||
|
poke(parameters[2], lt ? 1 : 0)
|
||||||
|
@pc += 4
|
||||||
|
end
|
||||||
|
|
||||||
|
def equals!
|
||||||
|
eq = peek(parameters[0]) == peek(parameters[1])
|
||||||
|
poke(parameters[2], eq ? 1 : 0)
|
||||||
|
@pc += 4
|
||||||
|
end
|
||||||
|
|
||||||
|
def halt!
|
||||||
|
log "halting!"
|
||||||
|
@stopped = true
|
||||||
|
end
|
||||||
|
|
||||||
|
def instruction
|
||||||
|
peek pc
|
||||||
|
end
|
||||||
|
|
||||||
|
def opcode
|
||||||
|
instruction % 100
|
||||||
|
end
|
||||||
|
|
||||||
|
def parameter_modes
|
||||||
|
[
|
||||||
|
instruction / 100 % 10,
|
||||||
|
instruction / 1000 % 10,
|
||||||
|
instruction / 10000 % 10,
|
||||||
|
]
|
||||||
|
end
|
||||||
|
|
||||||
|
def peek(address)
|
||||||
|
memory[address]
|
||||||
|
end
|
||||||
|
|
||||||
|
def poke(address, value)
|
||||||
|
log "poking #{value} into #{address}"
|
||||||
|
memory[address] = value
|
||||||
|
end
|
||||||
|
|
||||||
|
def log(message)
|
||||||
|
puts message if logging?
|
||||||
|
end
|
||||||
|
|
||||||
|
def logging?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -11,4 +11,4 @@ if [[ -z $source_file ]] ; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
time (cat ../data/$year/$day/input.txt | ruby -I$year/$day/lib $source_file)
|
time (cat ../data/$year/$day/input.txt | ruby -I$year/$day/lib -I$year/lib $source_file)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user