More intcode

This commit is contained in:
Bill Rossi 2025-12-06 10:19:08 -05:00
parent b004c936f0
commit d30e3f9600
4 changed files with 172 additions and 80 deletions

View File

@ -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
View 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
View 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

View File

@ -11,4 +11,4 @@ if [[ -z $source_file ]] ; then
exit 1
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)