Abstract intocode into separate files.

This commit is contained in:
Danila Fedorin 2020-12-04 18:17:39 -08:00
parent e62a0067e7
commit 161ee6e244
5 changed files with 132 additions and 67 deletions

24
day2.cr
View File

@ -1,25 +1,11 @@
require "./intcode.cr"
lines = File.read("day2.txt").lines.map(&.split(",").map(&.to_i32)).flatten
def run(lines, noun, verb)
lines[1] = noun
lines[2] = verb
pos = 0
loop do
case lines[pos]
when 1
lines[lines[pos+3]] = lines[lines[pos+1]] + lines[lines[pos+2]]
pos += 4
when 2
lines[lines[pos+3]] = lines[lines[pos+1]] * lines[lines[pos+2]]
pos += 4
when 99
break
end
end
lines[0]
end
100.times do |noun|
100.times do |verb|
if run(lines.dup, noun, verb) == 19690720
prog = lines.clone
prog[1] = noun
prog[2] = verb
if run(prog, [] of Int32)[1][0] == 19690720
puts 100*noun + verb
break
end

51
day5.cr
View File

@ -1,49 +1,4 @@
require "./intcode.cr"
lines = File.read("day5.txt").chomp.split(",").map(&.to_i32)
def run(lines, input)
output = [] of Int32
pos = 0
get = ->(x : Char, p : Int32) {
x == '0' ? lines[lines[pos+p]] : lines[pos+p]
}
loop do
str = "000" + lines[pos].to_s
case str
when .ends_with?("1")
lines[lines[pos+3]] = get.call(str[-3], 1) + get.call(str[-4], 2)
pos += 4
when .ends_with?("2")
lines[lines[pos+3]] = get.call(str[-3], 1) * get.call(str[-4], 2)
pos += 4
when .ends_with?("3")
lines[lines[pos+1]] = input.pop
pos += 2
when .ends_with?("4")
output << get.call(str[-3], 1)
pos += 2
when .ends_with?("5")
if get.call(str[-3], 1) != 0
pos = get.call(str[-4], 2)
else
pos += 3
end
when .ends_with?("6")
if get.call(str[-3], 1) == 0
pos = get.call(str[-4], 2)
else
pos += 3
end
when .ends_with?("7")
lines[lines[pos+3]] = (get.call(str[-3], 1) < get.call(str[-4], 2)) ? 1 : 0
pos += 4
when .ends_with?("8")
lines[lines[pos+3]] = (get.call(str[-3], 1) == get.call(str[-4], 2)) ? 1 : 0
pos += 4
when .ends_with?("99")
break
else
raise "aahhh #{str}"
end
end
{output, lines}
end
puts run(lines, [5])
puts run(lines.clone, [1])
puts run(lines.clone, [5])

35
day7.cr Normal file
View File

@ -0,0 +1,35 @@
require "./intcode.cr"
require "./intcode_fibers.cr"
prog = File.read("day7.txt").chomp.split(",").map(&.to_i32)
def chain_amplifiers(prog, perm, loop = false)
chans = perm.map { |f| new_interpreter(f, prog) }
chans.zip perm do |amp, freq|
amp[0].send freq
end
chans[0][0].send 0
i = 0
history = Array(Int32).new(chans.size, 0)
loop do
j = (i+1) % chans.size
break unless received = chans[i][1].receive
history[i] = received
chans[j][0].send received
i = j
break if i == 0 && !loop
end
history[4]
end
max_single = [0,1,2,3,4].permutations.max_of do |perm|
chain_amplifiers(prog.clone, perm)
end
puts max_single
max_cycled = [5,6,7,8,9].permutations.max_of do |perm|
chain_amplifiers(prog.clone, perm, loop=true)
end
puts max_cycled

47
intcode.cr Normal file
View File

@ -0,0 +1,47 @@
def run(lines, input)
output = [] of Int32
pos = 0
get = ->(x : Char, p : Int32) {
x == '0' ? lines[lines[pos+p]] : lines[pos+p]
}
loop do
str = "000" + lines[pos].to_s
case str
when .ends_with?("1")
lines[lines[pos+3]] = get.call(str[-3], 1) + get.call(str[-4], 2)
pos += 4
when .ends_with?("2")
lines[lines[pos+3]] = get.call(str[-3], 1) * get.call(str[-4], 2)
pos += 4
when .ends_with?("3")
lines[lines[pos+1]] = input.pop
pos += 2
when .ends_with?("4")
output << get.call(str[-3], 1)
pos += 2
when .ends_with?("5")
if get.call(str[-3], 1) != 0
pos = get.call(str[-4], 2)
else
pos += 3
end
when .ends_with?("6")
if get.call(str[-3], 1) == 0
pos = get.call(str[-4], 2)
else
pos += 3
end
when .ends_with?("7")
lines[lines[pos+3]] = (get.call(str[-3], 1) < get.call(str[-4], 2)) ? 1 : 0
pos += 4
when .ends_with?("8")
lines[lines[pos+3]] = (get.call(str[-3], 1) == get.call(str[-4], 2)) ? 1 : 0
pos += 4
when .ends_with?("99")
break
else
raise "Invalid instruction"
end
end
{output, lines}
end

42
intcode_fibers.cr Normal file
View File

@ -0,0 +1,42 @@
def new_interpreter(f, prog)
prog = prog.clone
input = Channel(Int32).new
output = Channel(Int32?).new
spawn do
op = ""
pc = 0
arg = ->(i : Int32) { op[-(3+i)] == '0' ? prog[prog[pc+1+i]] : prog[pc+1+i] }
loop do
op = "0000" + prog[pc].to_s
case op
when .ends_with? "1"
prog[prog[pc+3]] = arg.call(0) + arg.call(1)
pc += 4
when .ends_with? "2"
prog[prog[pc+3]] = arg.call(0) * arg.call(1)
pc += 4
when .ends_with? "3"
prog[prog[pc+1]] = input.receive
pc += 2
when .ends_with? "4"
output.send(arg.call(0))
pc += 2
when .ends_with? "5"
pc = arg.call(0) != 0 ? arg.call(1) : pc + 3
when .ends_with? "6"
pc = arg.call(0) == 0 ? arg.call(1) : pc + 3
when .ends_with? "7"
prog[prog[pc+3]] = arg.call(0) < arg.call(1) ? 1 : 0
pc += 4
when .ends_with? "8"
prog[prog[pc+3]] = arg.call(0) == arg.call(1) ? 1 : 0
pc += 4
when .ends_with? "99"
input.receive
output.send(nil)
break
end
end
end
{input, output}
end