diff --git a/day20/part1.lua b/day20/part1.lua new file mode 100755 index 0000000..02ed006 --- /dev/null +++ b/day20/part1.lua @@ -0,0 +1,64 @@ +#!/usr/bin/env luajit +require("utils") +require("grid") + +local f = io.open(arg[3]) +local line = f:read("*l") +local enhancer = {} +for char in chars(line) do + if char == "#" then + table.insert(enhancer, 1) + else + table.insert(enhancer, 0) + end +end +f:read("*l") +line = f:read("*l") +local image = grid(1, 1, #line, #line, 0) +local r, c = 0, 0 +while line ~= nil do + r = r + 1 + c = 0 + for char in chars(line) do + c = c + 1 + if char == "#" then + image:set(r, c, 1) + end + end + line = f:read("*l") +end + +function zoom(image, enhancer) + local newdefault = enhancer[image.default * (#enhancer - 1) + 1] + local newimage = grid(image.top - 1, image.left - 1, + image.height + 2, image.width + 2, newdefault) + for v, r, c in image:iter() do + newimage:set(r, c, v) + end + return newimage +end + +function enhance(image, enhancer) + local newimage = zoom(image, enhancer) + for _, r, c in newimage:iter() do + local index = 0 + for v, _, _ in image:neigh9(r, c) do + index = index * 2 + v + end + newimage:set(r, c, enhancer[index + 1]) + end + return newimage +end + +local function pprint(c) + if c == 0 + then return "." + else return "#" + end +end + +local counter = 0 +for v in enhance(enhance(image, enhancer), enhancer):iter() do + counter = counter + v +end +print(counter) diff --git a/day20/part2.lua b/day20/part2.lua new file mode 100755 index 0000000..3f7e24d --- /dev/null +++ b/day20/part2.lua @@ -0,0 +1,68 @@ +#!/usr/bin/env luajit +require("utils") +require("grid") + +local f = io.open(arg[3]) +local line = f:read("*l") +local enhancer = {} +for char in chars(line) do + if char == "#" then + table.insert(enhancer, 1) + else + table.insert(enhancer, 0) + end +end +f:read("*l") +line = f:read("*l") +local image = grid(1, 1, #line, #line, 0) +local r, c = 0, 0 +while line ~= nil do + r = r + 1 + c = 0 + for char in chars(line) do + c = c + 1 + if char == "#" then + image:set(r, c, 1) + end + end + line = f:read("*l") +end + +function zoom(image, enhancer) + local newdefault = enhancer[image.default * (#enhancer - 1) + 1] + local newimage = grid(image.top - 1, image.left - 1, + image.height + 2, image.width + 2, newdefault) + for v, r, c in image:iter() do + newimage:set(r, c, v) + end + return newimage +end + +function enhance(image, enhancer) + local newimage = zoom(image, enhancer) + for _, r, c in newimage:iter() do + local index = 0 + for v, _, _ in image:neigh9(r, c) do + index = index * 2 + v + end + newimage:set(r, c, enhancer[index + 1]) + end + return newimage +end + +local function pprint(c) + if c == 0 + then return "." + else return "#" + end +end + +for i = 1, 50 do + image = enhance(image, enhancer) +end + +local counter = 0 +for v in image:iter() do + counter = counter + v +end +print(counter) diff --git a/grid.lua b/grid.lua new file mode 100644 index 0000000..4eaeb61 --- /dev/null +++ b/grid.lua @@ -0,0 +1,83 @@ +local function set(self, r, c, v) + if r < self.top or r > self.bottom or c < self.left or c > self.right then + error(string.format("index (%d %d) out of bounds (%d..%d %d..%d)", + r, c, self.top, self.bottom, self.left, self.right)) + end + self.grid[r * self.width + c] = v +end + +local function get(self, r, c) + if r < self.top or r > self.bottom or c < self.left or c > self.right then + if self.default then + return self.default + else + error(string.format("index (%d %d) out of bounds (%d..%d %d..%d)", + r, c, self.top, self.bottom, self.left, self.right)) + end + end + local item = self.grid[r * self.width + c] + if item == nil and self.default then + return self.default + else + return item + end +end + +local function iter(self, r, c, h, w) + if r == nil then r = self.top end + if c == nil then c = self.left end + if h == nil then h = self.height end + if w == nil then w = self.width end + local r0, c0 = r, c + return function() + if r0 > r + h - 1 then return nil end + local rb, cb = r0, c0 + c0 = c0 + 1 + if c0 > c + w - 1 then + c0 = c + r0 = r0 + 1 + end + return self:get(rb, cb), rb, cb + end +end + +local function neigh9(self, r, c, exclude) + local iter = self:iter(r - 1, c - 1, 3, 3) + return function() + local i, ri, ci = iter() + if exclude and ri == r and ci == c then + local i, ri, ci = iter() + end + return i, ri, ci + end +end + +local function write(self, format) + if not format then format = function(i) + return string.format("%3s", i) + end end + for r = self.top, self.bottom do + for c = self.left, self.right do + io.write(format(self:get(r, c))) + end + io.write("\n") + end +end + +function grid(top, left, width, height, default) + return { + top = top, + left = left, + height = height, + width = width, + bottom = top + height - 1, + right = left + width - 1, + default = default, + grid = {}, + get = get, + set = set, + iter = iter, + neigh9 = neigh9, + write = write, + } +end