From 9efab871b1da41d5bb5f8ae04e00b406a4eac452 Mon Sep 17 00:00:00 2001 From: Felix Van der Jeugt Date: Sat, 18 Dec 2021 15:51:21 +0100 Subject: [PATCH] day 18 --- day18/part1.lua | 141 ++++++++++++++++++++++++++++++++++++++++++++++++ day18/part2.lua | 135 ++++++++++++++++++++++++++++++++++++++++++++++ utils.lua | 2 +- 3 files changed, 277 insertions(+), 1 deletion(-) create mode 100755 day18/part1.lua create mode 100755 day18/part2.lua diff --git a/day18/part1.lua b/day18/part1.lua new file mode 100755 index 0000000..038159d --- /dev/null +++ b/day18/part1.lua @@ -0,0 +1,141 @@ +#!/usr/bin/env luajit +require("utils") + +function parse(line) + local number = {} + local depth = 0 + for char in chars(line) do + if char == "[" then + depth = depth + 1 + elseif char == "]" then + depth = depth - 1 + elseif char ~= "," then + table.insert(number, { d=depth, n=tonumber(char) }) + end + end + return number +end + +function add(a, b) + local sum = {} + for i, digit in ipairs(a) do + table.insert(sum, { d = digit.d + 1, n = digit.n }) + end + for i, digit in ipairs(b) do + table.insert(sum, { d = digit.d + 1, n = digit.n }) + end + return sum +end + +function explode(a) + local new = {} + local exploded = false + local i = 1 + while i <= #a do + if exploded or a[i].d <= 4 then + table.insert(new, a[i]) + i = i + 1 + else + exploded = true + if #new > 0 then + new[#new].n = new[#new].n + a[i].n + end + table.insert(new, { d = a[i].d - 1, n = 0 }) + if #a >= i + 2 then + table.insert(new, { d = a[i + 2].d, n = a[i + 1].n + a[i + 2].n }) + end + i = i + 3 + end + end + return exploded, new +end + +-- printtable({ explode(parse("[[[[[9,8],1],2],3],4]")) }) +-- printtable({ explode(parse("[7,[6,[5,[4,[3,2]]]]]")) }) +-- printtable({ explode(parse("[[6,[5,[4,[3,2]]]],1]")) }) +-- printtable({ explode(parse("[[3,[2,[1,[7,3]]]],[6,[5,[4,[3,2]]]]]")) }) +-- printtable({ explode(parse("[[3,[2,[8,0]]],[9,[5,[4,[3,2]]]]]")) }) + +function split(a) + local new = {} + local split = false + for i, digit in ipairs(a) do + if split or digit.n < 10 then + table.insert(new, digit) + else + split = true + table.insert(new, { d = digit.d + 1, n = math.floor(digit.n / 2) }) + table.insert(new, { d = digit.d + 1, n = math.ceil(digit.n / 2) }) + end + end + return split, new +end + +function reduce(a) + local changed = true + repeat + changed, a = explode(a) + if not changed then + changed, a = split(a) + end + until not changed + return a +end + +function reconstruct(number) + local function go(d, c) + local left, right + if number[c].d > d then + left, c = go(d + 1, c) + right, c = go(d + 1, c) + return { left, right }, c + else + return number[c].n, c + 1 + end + end + return go(0, 1) +end + +function printnumber(a) + local function go(a) + if type(a) == "number" then + io.write(tostring(a)) + else + io.write("[") + go(a[1]) + io.write(",") + go(a[2]) + io.write("]") + end + end + go(reconstruct(a)) + io.write("\n") +end + +-- printnumber(reduce(parse("[[[[[4,3],4],4],[7,[[8,4],9]]],[1,1]]"))) +-- printnumber(reduce(add(parse("[[[[4,3],4],4],[7,[[8,4],9]]]"),parse("[1,1]")))) +-- printnumber(parse("[[[0,[4,5]],[0,0]],[[[4,5],[2,6]],[9,5]]]")) +-- printtable(parse("[[[0,[4,5]],[0,0]],[[[4,5],[2,6]],[9,5]]]")) +-- printnumber(add(parse("[[[0,[4,5]],[0,0]],[[[4,5],[2,6]],[9,5]]]"),parse("[7,[[[3,7],[4,3]],[[6,3],[8,8]]]]"))) +-- printnumber(reduce(add(parse("[[[0,[4,5]],[0,0]],[[[4,5],[2,6]],[9,5]]]"),parse("[7,[[[3,7],[4,3]],[[6,3],[8,8]]]]")))) + +function magnitude(a) + local function go(a) + if type(a) == "number" then + return a + else + return 3 * go(a[1]) + 2 * go(a[2]) + end + end + return go(reconstruct(a)) +end + +local f = io.open(arg[3]) +local number = parse(f:read("*l")) +local line = f:read("*l") +while line do + number = reduce(add(number, parse(line))) + line = f:read("*l") +end + +print(magnitude(number)) diff --git a/day18/part2.lua b/day18/part2.lua new file mode 100755 index 0000000..7528750 --- /dev/null +++ b/day18/part2.lua @@ -0,0 +1,135 @@ +#!/usr/bin/env luajit +require("utils") + +function parse(line) + local number = {} + local depth = 0 + for char in chars(line) do + if char == "[" then + depth = depth + 1 + elseif char == "]" then + depth = depth - 1 + elseif char ~= "," then + table.insert(number, { d=depth, n=tonumber(char) }) + end + end + return number +end + +function explode(a) + local new = {} + local exploded = false + local i = 1 + while i <= #a do + if exploded or a[i].d <= 4 then + table.insert(new, a[i]) + i = i + 1 + else + exploded = true + if #new > 0 then + new[#new].n = new[#new].n + a[i].n + end + table.insert(new, { d = a[i].d - 1, n = 0 }) + if #a >= i + 2 then + table.insert(new, { d = a[i + 2].d, n = a[i + 1].n + a[i + 2].n }) + end + i = i + 3 + end + end + return exploded, new +end + +function split(a) + local new = {} + local split = false + for i, digit in ipairs(a) do + if split or digit.n < 10 then + table.insert(new, digit) + else + split = true + table.insert(new, { d = digit.d + 1, n = math.floor(digit.n / 2) }) + table.insert(new, { d = digit.d + 1, n = math.ceil(digit.n / 2) }) + end + end + return split, new +end + +function reduce(a) + local changed = true + repeat + changed, a = explode(a) + if not changed then + changed, a = split(a) + end + until not changed + return a +end + +function add(a, b) + local sum = {} + for i, digit in ipairs(a) do + table.insert(sum, { d = digit.d + 1, n = digit.n }) + end + for i, digit in ipairs(b) do + table.insert(sum, { d = digit.d + 1, n = digit.n }) + end + return reduce(sum) +end + +function reconstruct(number) + local function go(d, c) + local left, right + if number[c].d > d then + left, c = go(d + 1, c) + right, c = go(d + 1, c) + return { left, right }, c + else + return number[c].n, c + 1 + end + end + return go(0, 1) +end + +function printnumber(a) + local function go(a) + if type(a) == "number" then + io.write(tostring(a)) + else + io.write("[") + go(a[1]) + io.write(",") + go(a[2]) + io.write("]") + end + end + go(reconstruct(a)) + io.write("\n") +end + +function magnitude(a) + local function go(a) + if type(a) == "number" then + return a + else + return 3 * go(a[1]) + 2 * go(a[2]) + end + end + return go(reconstruct(a)) +end + +local numbers = {} +for line in io.lines(arg[3]) do + table.insert(numbers, parse(line)) +end + +local max = 0 +for i, a in pairs(numbers) do + for j, b in pairs(numbers) do + if i ~= j then + local m = magnitude(add(a, b)) + if m > max then max = m end + end + end +end + +print(max) diff --git a/utils.lua b/utils.lua index 867a0b6..7cf84d2 100644 --- a/utils.lua +++ b/utils.lua @@ -32,7 +32,7 @@ function printtable(t, nonewline) printtable(v, true) io.write(") ") else - io.write(v.." ") + io.write(tostring(v).." ") end end if not nonewline then