67 lines
1.6 KiB
Lua
67 lines
1.6 KiB
Lua
local commands = {}
|
|
|
|
for line in io.lines() do
|
|
local name, arg = line:match('^(%l+) ([+-]%d+)$')
|
|
local intarg = tonumber(arg:gsub('%+', ''), 10)
|
|
table.insert(commands, {name=name, arg=intarg, ran=false})
|
|
end
|
|
|
|
local function nop_cmd(arg, acc, pos)
|
|
return acc, pos + 1
|
|
end
|
|
local function acc_cmd(arg, acc, pos)
|
|
return acc + arg, pos + 1
|
|
end
|
|
local function jmp_cmd(arg, acc, pos)
|
|
return acc, pos + arg
|
|
end
|
|
|
|
local functions = {
|
|
nop=nop_cmd,
|
|
acc=acc_cmd,
|
|
jmp=jmp_cmd,
|
|
}
|
|
|
|
local function reset()
|
|
for _, command in ipairs(commands) do
|
|
command.ran = false
|
|
end
|
|
end
|
|
|
|
--[[
|
|
This function runs the program and returns two values:
|
|
- true if the program ends because of its last instruction
|
|
- false if the program ends because a command was already ran
|
|
--]]
|
|
local function run()
|
|
local acc, pos = 0, 1
|
|
while true do
|
|
if pos > #commands then
|
|
return true, acc
|
|
end
|
|
local command = commands[pos]
|
|
if command.ran then
|
|
return false, acc
|
|
end
|
|
acc, pos = functions[command.name](command.arg, acc, pos)
|
|
command.ran = true
|
|
end
|
|
end
|
|
|
|
-- Part 1
|
|
print(select(2, run()))
|
|
|
|
-- Part 2
|
|
for i, command in ipairs(commands) do
|
|
if (command.name == "nop" or command.name == "jmp") and command.arg ~= 0 then
|
|
command.name = command.name == "nop" and "jmp" or "nop"
|
|
reset()
|
|
local ended, acc = run()
|
|
if ended then
|
|
print(acc)
|
|
return
|
|
end
|
|
command.name = command.name == "nop" and "jmp" or "nop"
|
|
end
|
|
end
|