diff --git a/2020/8/day8.lua b/2020/8/day8.lua new file mode 100644 index 0000000..3d8810a --- /dev/null +++ b/2020/8/day8.lua @@ -0,0 +1,66 @@ +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 diff --git a/README.md b/README.md index 35190c8..28236cc 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ My solutions to the Advent of Code puzzles. 5 ██ ██ ██ ██ 6 ██ ██ ██ 7 ██ ██ ██ - 8 ██ ██ + 8 ██ ██ ██ 9 ██ 10 ██ ██ 11 ██ ██