Advent of Code 2019 - Lua
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
3.7 KiB

5 years ago
function get_param(state, arg)
local param_mode = state.mem[state.pos] // (10 ^ (arg + 1)) % 10
if #state.mem < state.pos + arg then
print(string.format("Error: Opcode too short at end of memory: %d", state.pos))
os.exit(false)
end
local arg = state.mem[state.pos + arg]
if param_mode == 0 then
arg = arg + 1
elseif param_mode == 2 then
arg = arg + state.relbase
end
return arg
end
function read_mem(state, arg)
local param_mode = state.mem[state.pos] // (10 ^ (arg + 1)) % 10
local arg = get_param(state, arg)
if param_mode == 1 then
return arg
end
arg = state.mem[arg]
if not arg then
return 0
end
return arg
end
function write_mem(state, arg, val)
local param_mode = state.mem[state.pos] // (10 ^ (arg + 1)) % 10
local arg = get_param(state, arg)
if param_mode == 1 then
print(string.format("Error: Invalid inmediate write: %d", arg))
end
state.mem[arg] = val
end
function interpret(state)
if not state.mem then
state.mem = state
end
if not state.pos then
state.pos = 1
state.relbase = 1
end
if not state.input then
state.input = input_stdin
end
if not state.output then
state.output = output_stdout
end
while true do
if #state.mem < state.pos then
print(string.format("Instruction pointer ran off of memory"))
os.exit(false)
end
local opcode = state.mem[state.pos] % 100
local instr_size = 1
if opcode == 1 then
write_mem(state, 3, read_mem(state, 1) + read_mem(state, 2))
instr_size = 4
elseif opcode == 2 then
write_mem(state, 3, read_mem(state, 1) * read_mem(state, 2))
instr_size = 4
elseif opcode == 3 then
local val = state.input()
if not val then return true end
write_mem(state, 1, val)
instr_size = 2
elseif opcode == 4 then
state.output(read_mem(state, 1))
instr_size = 2
elseif opcode == 5 then
instr_size = 3
if read_mem(state, 1) ~= 0 then
state.pos = read_mem(state, 2) + 1
instr_size = 0
end
elseif opcode == 6 then
instr_size = 3
if read_mem(state, 1) == 0 then
state.pos = read_mem(state, 2) + 1
instr_size = 0
end
elseif opcode == 7 then
write_mem(state, 3, read_mem(state, 1) < read_mem(state, 2) and 1 or 0)
instr_size = 4
elseif opcode == 8 then
write_mem(state, 3, read_mem(state, 1) == read_mem(state, 2) and 1 or 0)
instr_size = 4
elseif opcode == 9 then
state.relbase = state.relbase + read_mem(state, 1)
instr_size = 2
elseif opcode == 99 then
return false
else
print(string.format("Error: Invalid opcode %d at %d", opcode, state.pos - 1))
os.exit(false)
end
state.pos = state.pos + instr_size
end
end
function input_stdin()
io.stdout:write("> ")
return io.stdin:read("n")
end
function output_stdout(val)
io.stdout:write(val)
io.stdout:write("\n")
end
function input_array(array)
function inner()
return table.remove(array, 1)
end
return inner
end
function output_array(array)
function inner(val)
table.insert(array, val)
end
return inner
end
file = io.open(arg[1])
program = {}
for num in string.gmatch(file:read(), "(-?%d+),?") do
table.insert(program, tonumber(num))
end
file:close()
interpret(program)