AdventOfCode-2019/intcode_fibers.cr

62 lines
1.5 KiB
Crystal

def new_interpreter(f, p)
prog = {} of Int64 => Int64
p.each_with_index do |v, i|
prog[i.to_i64] = v.to_i64
end
input = Channel(Int64).new
output = Channel(Int64?).new
spawn do
op = ""
pc = 0_i64
base = 0_i64
index = ->(i : Int32) {
case op[-(3+i)]
when '0'
prog[pc+1+i]
when '1'
pc+1+i
else
prog[pc+1+i] + base
end
}
get = ->(i : Int32) { prog[index.call(i)]? || 0_i64 }
set = ->(i : Int32, v : Int64) { prog[index.call(i)] = v }
loop do
op = "0000" + prog[pc].to_s
case op
when .ends_with? "1"
set.call(2, get.call(0) + get.call(1))
pc += 4
when .ends_with? "2"
set.call(2, get.call(0) * get.call(1))
pc += 4
when .ends_with? "3"
set.call(0, input.receive)
pc += 2
when .ends_with? "4"
output.send(get.call(0))
pc += 2
when .ends_with? "5"
pc = get.call(0) != 0 ? get.call(1) : pc + 3
when .ends_with? "6"
pc = get.call(0) == 0 ? get.call(1) : pc + 3
when .ends_with? "7"
set.call(2, get.call(0) < get.call(1) ? 1_i64 : 0_i64)
pc += 4
when .ends_with? "8"
set.call(2, get.call(0) == get.call(1) ? 1_i64 : 0_i64)
pc += 4
when .ends_with? "99"
input.receive
output.send(nil)
break
when .ends_with? "9"
base += get.call(0)
pc += 2
end
end
end
{input, output}
end