Skip to content

Instantly share code, notes, and snippets.

@Arkoniak
Created December 5, 2019 08:27
Show Gist options
  • Save Arkoniak/a0cc7e98b57d1b40a5b767d58c868f12 to your computer and use it in GitHub Desktop.
Save Arkoniak/a0cc7e98b57d1b40a5b767d58c868f12 to your computer and use it in GitHub Desktop.
mutable struct Code
code::Vector{Int}
cur::Int
input::Int
output::Int
eop::Bool
end
str2prog(s) = parse.(Int, split(s, ","))
Code(s::String) = Code(str2prog(s), 1, 0, 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,
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(code::Code) = Instruction(code.code[code.cur])
function apply(code::Code, instruction::Instruction)
if instruction.op == 99
code.eop = true
elseif instruction.op == 1
a1 = instruction.modes[1] == 1 ? code.code[code.cur + 1] : code.code[code.code[code.cur + 1] + 1]
a2 = instruction.modes[2] == 1 ? code.code[code.cur + 2] : code.code[code.code[code.cur + 2] + 1]
code.code[code.code[code.cur + 3] + 1] = a1 + a2
code.cur += 4
elseif instruction.op == 2
a1 = instruction.modes[1] == 1 ? code.code[code.cur + 1] : code.code[code.code[code.cur + 1] + 1]
a2 = instruction.modes[2] == 1 ? code.code[code.cur + 2] : code.code[code.code[code.cur + 2] + 1]
code.code[code.code[code.cur + 3] + 1] = a1 * a2
code.cur += 4
elseif instruction.op == 3
code.code[code.code[code.cur + 1] + 1] = code.input
code.cur += 2
elseif instruction.op == 4
code.output = code.code[code.code[code.cur + 1] + 1]
code.cur += 2
elseif instruction.op == 5
a1 = instruction.modes[1] == 1 ? code.code[code.cur + 1] : code.code[code.code[code.cur + 1] + 1]
a2 = instruction.modes[2] == 1 ? code.code[code.cur + 2] : code.code[code.code[code.cur + 2] + 1]
if a1 != 0
code.cur = a2 + 1
else
code.cur += 3
end
elseif instruction.op == 6
a1 = instruction.modes[1] == 1 ? code.code[code.cur + 1] : code.code[code.code[code.cur + 1] + 1]
a2 = instruction.modes[2] == 1 ? code.code[code.cur + 2] : code.code[code.code[code.cur + 2] + 1]
if a1 == 0
code.cur = a2 + 1
else
code.cur += 3
end
elseif instruction.op == 7
a1 = instruction.modes[1] == 1 ? code.code[code.cur + 1] : code.code[code.code[code.cur + 1] + 1]
a2 = instruction.modes[2] == 1 ? code.code[code.cur + 2] : code.code[code.code[code.cur + 2] + 1]
a3 = code.code[code.cur + 3] + 1
if a1 < a2
code.code[a3] = 1
else
code.code[a3] = 0
end
code.cur += 4
elseif instruction.op == 8
a1 = instruction.modes[1] == 1 ? code.code[code.cur + 1] : code.code[code.code[code.cur + 1] + 1]
a2 = instruction.modes[2] == 1 ? code.code[code.cur + 2] : code.code[code.code[code.cur + 2] + 1]
a3 = code.code[code.cur + 3] + 1
if a1 == a2
code.code[a3] = 1
else
code.code[a3] = 0
end
code.cur += 4
end
end
function run(code::Code)
while !code.eop
instruction = Instruction(code)
apply(code, instruction)
end
end
function run(code::Code, input::Int)
code.input = input
run(code)
end
## Some tests
code = Code("3,9,7,9,10,9,4,9,99,-1,8")
run(code, 6)
@assert code.output == 1
code = Code("3,9,7,9,10,9,4,9,99,-1,8")
run(code, 8)
@assert code.output == 0
code = Code("3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9")
run(code, 0)
@assert code.output == 0
code = Code("3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9")
run(code, 1)
@assert code.output == 1
code = Code("3,12,6,12,15,1,13,14,13,4,13,99,-1,0,1,9")
run(code, -1)
@assert code.output == 1
## Calculation
code = Code(readlines("input.txt")[1])
run(code, 5)
println(code.output)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment