Skip to content

Instantly share code, notes, and snippets.

@Arkoniak
Created December 9, 2019 08:22
Show Gist options
  • Save Arkoniak/ce75c3148dce5923d4a24a768fae66f9 to your computer and use it in GitHub Desktop.
Save Arkoniak/ce75c3148dce5923d4a24a768fae66f9 to your computer and use it in GitHub Desktop.
mutable struct Prog
code::Vector{Int}
cur::Int
input::Vector{Int}
output::Vector{Int}
relative_base::Int
eop::Bool
end
str2prog(s) = parse.(Int, split(s, ","))
Prog(s::String) = Prog(vcat(str2prog(s), zeros(Int, 10000)), 1, [], [], 0, false)
struct Instruction
op::Int
modes::Vector{Int}
end
function Instruction(op_code::Int)
ops = Dict{Int, Int}(
1 => 3,
2 => 3,
3 => 1,
4 => 1,
5 => 2,
6 => 2,
7 => 3,
8 => 3,
9 => 1,
99 => 0
)
op = mod(op_code, 100)
modes_code = div(op_code, 100)
modes = zeros(ops[op])
for i in 1:ops[op]
modes[i] = mod(modes_code, 10)
modes_code = div(modes_code, 10)
end
Instruction(op, modes)
end
Instruction(prog::Prog) = Instruction(prog.code[prog.cur])
function take(prog::Prog, mode, offset)
if mode == 0
return prog.code[prog.code[prog.cur + offset] + 1]
elseif mode == 1
return prog.code[prog.cur + offset]
else
return prog.code[prog.code[prog.cur + offset] + prog.relative_base + 1]
end
end
function update!(prog::Prog, value, offset, mode = 0)
if mode == 0
prog.code[prog.code[prog.cur + offset] + 1] = value
elseif mode == 2
prog.code[prog.code[prog.cur + offset] + prog.relative_base + 1] = value
end
end
function apply(prog::Prog, instruction::Instruction)
#println(instruction)
if instruction.op == 99
prog.eop = true
elseif instruction.op == 1
a1 = take(prog, instruction.modes[1], 1)
a2 = take(prog, instruction.modes[2], 2)
update!(prog, a1 + a2, 3, instruction.modes[3])
prog.cur += 4
elseif instruction.op == 2
a1 = take(prog, instruction.modes[1], 1)
a2 = take(prog, instruction.modes[2], 2)
update!(prog, a1 * a2, 3, instruction.modes[3])
prog.cur += 4
elseif instruction.op == 3
update!(prog, popfirst!(prog.input), 1, instruction.modes[1])
prog.cur += 2
elseif instruction.op == 4
push!(prog.output, take(prog, instruction.modes[1], 1))
prog.cur += 2
elseif instruction.op == 5
a1 = take(prog, instruction.modes[1], 1)
a2 = take(prog, instruction.modes[2], 2)
prog.cur = a1 != 0 ? a2 + 1 : prog.cur + 3
elseif instruction.op == 6
a1 = take(prog, instruction.modes[1], 1)
a2 = take(prog, instruction.modes[2], 2)
prog.cur = a1 == 0 ? a2 + 1 : prog.cur + 3
elseif instruction.op == 7
a1 = take(prog, instruction.modes[1], 1)
a2 = take(prog, instruction.modes[2], 2)
update!(prog, a1 < a2 ? 1 : 0, 3, instruction.modes[3])
prog.cur += 4
elseif instruction.op == 8
a1 = take(prog, instruction.modes[1], 1)
a2 = take(prog, instruction.modes[2], 2)
update!(prog, a1 == a2 ? 1 : 0, 3, instruction.modes[3])
prog.cur += 4
elseif instruction.op == 9
prog.relative_base += take(prog, instruction.modes[1], 1)
prog.cur += 2
end
end
function run(prog::Prog, input::Vector{Int})
prog.input = input
while !prog.eop
instruction = Instruction(prog)
apply(prog, instruction)
end
prog.output
end
run(prog) = run(prog, Int[])
## Problem itself
# Part 1
prog = Prog(readline("input.txt"))
println(run(prog, [1])[1])
# Part 2
prog = Prog(readline("input.txt"))
println(run(prog, [2])[1])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment