50 lines
1.3 KiB
Lua
50 lines
1.3 KiB
Lua
#!/usr/bin/env lua
|
|
-- Parse parentheses, evaluating sub-expressions using another function
|
|
local function eval(expr, eval_func)
|
|
-- Remove any extra parenthses around the entire expression
|
|
while expr:find("^%b()$") do
|
|
expr = expr:sub(2, #expr - 1)
|
|
end
|
|
|
|
-- Parse all of the outermost parentheses recursively
|
|
local matches = 0
|
|
repeat
|
|
expr, matches = expr:gsub("%b()", function (subexpr) return eval(subexpr, eval_func) end)
|
|
until matches < 1
|
|
|
|
return eval_func(expr)
|
|
end
|
|
|
|
local function part1_eval(expr)
|
|
local left, operator
|
|
for token in expr:gmatch "%S+" do
|
|
if left == nil then
|
|
left = tonumber(token)
|
|
elseif operator == nil then
|
|
operator = token
|
|
elseif operator == "+" then
|
|
left = left + tonumber(token)
|
|
operator = nil
|
|
elseif operator == "*" then
|
|
left = left * tonumber(token)
|
|
operator = nil
|
|
else
|
|
error("unexpected operator!")
|
|
end
|
|
end
|
|
return left
|
|
end
|
|
|
|
local function part2_eval(expr)
|
|
return eval(expr:gsub("(%d+%s+[%d%+%s]+%s+%d+)", "(%1)"), part1_eval)
|
|
end
|
|
|
|
local part1 = 0
|
|
local part2 = 0
|
|
for line in io.lines() do
|
|
part1 = part1 + eval(line, part1_eval)
|
|
part2 = part2 + eval(line, part2_eval)
|
|
end
|
|
print(part1)
|
|
print(part2)
|