parent
9746694a7b
commit
12d3bd86be
|
@ -0,0 +1,173 @@
|
|||
-- Three-dimensional table of cubes.
|
||||
-- {x={y={z=true}}}
|
||||
local cubes = {}
|
||||
-- Four-dimensional!
|
||||
local hypercube = {}
|
||||
|
||||
local i = 0
|
||||
for line in io.lines() do
|
||||
i = i + 1
|
||||
-- Create deep copies immediately
|
||||
local row, row2 = {}, {}
|
||||
line:gsub(".", function (c) table.insert(row, {c == '#'}) end)
|
||||
line:gsub(".", function (c) table.insert(row2, {{c == '#'}}) end)
|
||||
cubes[i] = row
|
||||
hypercube[i] = row2
|
||||
end
|
||||
|
||||
|
||||
local function list_neighbors(x, y, z, w)
|
||||
local neighbors = {}
|
||||
for dx = -1, 1 do
|
||||
for dy = -1, 1 do
|
||||
for dz = -1, 1 do
|
||||
if w then
|
||||
for dw = -1, 1 do
|
||||
if dx ~= 0 or dy ~= 0 or dz ~= 0 or dw ~= 0 then
|
||||
table.insert(neighbors, {x+dx, y+dy, z+dz, w+dw})
|
||||
end
|
||||
end
|
||||
else
|
||||
if dx ~= 0 or dy ~= 0 or dz ~= 0 then
|
||||
table.insert(neighbors, {x+dx, y+dy, z+dz})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return neighbors
|
||||
end
|
||||
|
||||
local function count_active(x, y, z)
|
||||
local total = 0
|
||||
for _, neighbor in ipairs(list_neighbors(x, y, z)) do
|
||||
local nx, ny, nz = table.unpack(neighbor)
|
||||
if cubes[nx] and cubes[nx][ny] and cubes[nx][ny][nz] then
|
||||
total = total + 1
|
||||
end
|
||||
end
|
||||
return total
|
||||
end
|
||||
|
||||
local function cycle()
|
||||
local new_cubes = {}
|
||||
-- Set of new neighboring cubes that will be checked after the first loop
|
||||
local new_neighbors = {}
|
||||
for x, row in pairs(cubes) do
|
||||
new_cubes[x] = {}
|
||||
for y, column in pairs(row) do
|
||||
new_cubes[x][y] = {}
|
||||
for z, state in pairs(column) do
|
||||
local active = count_active(x, y, z)
|
||||
new_cubes[x][y][z] = (state and active == 2) or active == 3
|
||||
-- Load the new neighbors if the cube was active
|
||||
if state then
|
||||
for _, neighbor in ipairs(list_neighbors(x, y, z)) do
|
||||
new_neighbors[neighbor] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for neighbor, _ in pairs(new_neighbors) do
|
||||
local x, y, z = table.unpack(neighbor)
|
||||
local active = count_active(x, y, z)
|
||||
if active == 3 then
|
||||
if not new_cubes[x] then
|
||||
new_cubes[x] = {}
|
||||
end
|
||||
if not new_cubes[x][y] then
|
||||
new_cubes[x][y] = {}
|
||||
end
|
||||
new_cubes[x][y][z] = true
|
||||
end
|
||||
end
|
||||
cubes = new_cubes
|
||||
end
|
||||
|
||||
for _ = 1, 6 do
|
||||
cycle()
|
||||
end
|
||||
local part1 = 0
|
||||
for _, row in pairs(cubes) do
|
||||
for _, column in pairs(row) do
|
||||
for _, state in pairs(column) do
|
||||
if state then
|
||||
part1 = part1 + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
print(part1)
|
||||
|
||||
-- I'm lazy as always: copy-pasting half of the code to add the fourth dimension.
|
||||
local function count_hyper_active(x, y, z, w)
|
||||
local total = 0
|
||||
for _, neighbor in ipairs(list_neighbors(x, y, z, w)) do
|
||||
local nx, ny, nz, nw = table.unpack(neighbor)
|
||||
if hypercube[nx] and hypercube[nx][ny] and hypercube[nx][ny][nz] and hypercube[nx][ny][nz][nw] then
|
||||
total = total + 1
|
||||
end
|
||||
end
|
||||
return total
|
||||
end
|
||||
|
||||
-- Mmmhhh… Tasty O(n⁴)
|
||||
local function hyper_cycle()
|
||||
local new_hypercube = {}
|
||||
-- Set of new neighboring cubes that will be checked after the first loop
|
||||
local new_neighbors = {}
|
||||
for x, plan in pairs(hypercube) do
|
||||
new_hypercube[x] = {}
|
||||
for y, row in pairs(plan) do
|
||||
new_hypercube[x][y] = {}
|
||||
for z, column in pairs(row) do
|
||||
new_hypercube[x][y][z] = {}
|
||||
for w, state in pairs(column) do
|
||||
local active = count_hyper_active(x, y, z, w)
|
||||
new_hypercube[x][y][z][w] = (state and active == 2) or active == 3
|
||||
-- Load the new neighbors if the cube was active
|
||||
if state then
|
||||
for _, neighbor in ipairs(list_neighbors(x, y, z, w)) do
|
||||
new_neighbors[neighbor] = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
for neighbor, _ in pairs(new_neighbors) do
|
||||
local x, y, z, w = table.unpack(neighbor)
|
||||
local active = count_hyper_active(x, y, z, w)
|
||||
if active == 3 then
|
||||
if not new_hypercube[x] then
|
||||
new_hypercube[x] = {}
|
||||
end
|
||||
if not new_hypercube[x][y] then
|
||||
new_hypercube[x][y] = {}
|
||||
end
|
||||
if not new_hypercube[x][y][z] then
|
||||
new_hypercube[x][y][z] = {}
|
||||
end
|
||||
new_hypercube[x][y][z][w] = true
|
||||
end
|
||||
end
|
||||
hypercube = new_hypercube
|
||||
end
|
||||
|
||||
for _ = 1, 6 do
|
||||
hyper_cycle()
|
||||
end
|
||||
local part2 = 0
|
||||
for _, plan in pairs(hypercube) do
|
||||
for _, row in pairs(plan) do
|
||||
for _, column in pairs(row) do
|
||||
for _, state in pairs(column) do
|
||||
if state then
|
||||
part2 = part2 + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
print(part2)
|
Loading…
Reference in New Issue