1
0
Fork 0

2020 day 11

This commit is contained in:
Lucidiot 2020-12-11 06:45:06 +01:00
parent bfef11fd67
commit 0fa66344bd
Signed by: lucidiot
GPG Key ID: 3358C1CA6906FB8D
2 changed files with 121 additions and 1 deletions

120
2020/11/day11.lua Normal file
View File

@ -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())

View File

@ -21,7 +21,7 @@ is acceptable; anything goes as long as I solve it myself!
8 ██ ██ ██
9 ██ ██
10 ██ ██ ██
11 ██ ██
11 ██ ██ ██
12 ██ ██
13 ██
14 ██ ██