adventofcode-2021/grid.lua

90 lines
2.0 KiB
Lua

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
local function grow(self)
self.height = self.height + 1
self.bottom = self.bottom + 1
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,
grow = grow,
}
end