2020 day 11
This commit is contained in:
parent
bfef11fd67
commit
0fa66344bd
|
@ -0,0 +1,120 @@
|
|||
FLOOR, EMPTY, OCCUPIED = 0, 1, 2
|
||||
|
||||
-- Table of tables of integers representing states.
|
||||
local states = {}
|
||||
|
||||
for line in io.lines() do
|
||||
local row = {}
|
||||
local state_mappings = {["."]=FLOOR, L=EMPTY, ["#"]=OCCUPIED}
|
||||
line:gsub(".", function (c) table.insert(row, state_mappings[c]) end)
|
||||
table.insert(states, row)
|
||||
end
|
||||
|
||||
-- Deep copy of the table to keep it for part 2
|
||||
local initial = {}
|
||||
for x, row in ipairs(states) do
|
||||
initial[x] = {}
|
||||
for y, tile in ipairs(row) do
|
||||
initial[x][y] = tile
|
||||
end
|
||||
end
|
||||
|
||||
local function iteration(func)
|
||||
local modified = false
|
||||
local new_states = {}
|
||||
for x, row in ipairs(states) do
|
||||
new_states[x] = {}
|
||||
for y, tile in ipairs(row) do
|
||||
local result = func(x, y, tile)
|
||||
modified = modified or tile ~= result
|
||||
new_states[x][y] = result
|
||||
end
|
||||
end
|
||||
states = new_states
|
||||
return modified
|
||||
end
|
||||
|
||||
local function is_occupied(x, y)
|
||||
if x < 1 or y < 1 then
|
||||
return 0
|
||||
end
|
||||
if states[x] ~= nil and states[x][y] == OCCUPIED then
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
local function count_occupied()
|
||||
local total = 0
|
||||
for x, row in ipairs(states) do
|
||||
for y = 1, #row do
|
||||
total = total + is_occupied(x, y)
|
||||
end
|
||||
end
|
||||
return total
|
||||
end
|
||||
|
||||
local function part1(x, y, tile)
|
||||
if tile == FLOOR then
|
||||
return FLOOR
|
||||
end
|
||||
local adjacent =
|
||||
is_occupied(x-1, y-1)
|
||||
+ is_occupied(x, y-1)
|
||||
+ is_occupied(x+1, y-1)
|
||||
+ is_occupied(x-1, y)
|
||||
+ is_occupied(x+1, y)
|
||||
+ is_occupied(x-1, y+1)
|
||||
+ is_occupied(x, y+1)
|
||||
+ is_occupied(x+1, y+1)
|
||||
if tile == EMPTY and adjacent == 0 then
|
||||
return OCCUPIED
|
||||
elseif tile == OCCUPIED and adjacent >= 4 then
|
||||
return EMPTY
|
||||
end
|
||||
return tile
|
||||
end
|
||||
|
||||
-- Find a seat iteratively in a given direction
|
||||
local function find_occupied_seat(pos_x, pos_y, dir_x, dir_y)
|
||||
local i, j = pos_x + dir_x, pos_y + dir_y
|
||||
while i >= 1 and j >= 1 and i <= #states and j <= #states[i] do
|
||||
local tile = states[i][j]
|
||||
if tile == OCCUPIED then
|
||||
return 1
|
||||
elseif tile == EMPTY then
|
||||
return 0
|
||||
end
|
||||
i, j = i + dir_x, j + dir_y
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
local function part2(x, y, tile)
|
||||
if tile == FLOOR then
|
||||
return tile
|
||||
end
|
||||
local adjacent =
|
||||
find_occupied_seat(x, y, 1, 1)
|
||||
+ find_occupied_seat(x, y, 0, 1)
|
||||
+ find_occupied_seat(x, y, -1, 1)
|
||||
+ find_occupied_seat(x, y, 1, 0)
|
||||
+ find_occupied_seat(x, y, -1, 0)
|
||||
+ find_occupied_seat(x, y, 1, -1)
|
||||
+ find_occupied_seat(x, y, 0, -1)
|
||||
+ find_occupied_seat(x, y, -1, -1)
|
||||
if tile == EMPTY and adjacent == 0 then
|
||||
return OCCUPIED
|
||||
elseif tile == OCCUPIED and adjacent >= 5 then
|
||||
return EMPTY
|
||||
end
|
||||
return tile
|
||||
end
|
||||
|
||||
repeat until iteration(part1) == false
|
||||
print(count_occupied())
|
||||
|
||||
states = initial
|
||||
repeat until iteration(part2) == false
|
||||
print(count_occupied())
|
Loading…
Reference in New Issue