158 lines
3.2 KiB
Lua
158 lines
3.2 KiB
Lua
io.input("test")
|
|
--io.input("input")
|
|
|
|
function p2s( x, y )
|
|
return string.format("%d,%d", x, y)
|
|
end
|
|
|
|
function s2p( s )
|
|
local x, y = string.match(s,"(-?%d+),(-?%d+)")
|
|
x = tonumber(x)
|
|
y = tonumber(y)
|
|
return x, y
|
|
end
|
|
|
|
function neighbors(x, y)
|
|
local n = {}
|
|
n.NW = p2s( x-1, y-1)
|
|
n.N = p2s( x, y-1)
|
|
n.NE = p2s( x+1, y-1)
|
|
n.E = p2s( x+1, y )
|
|
n.SE = p2s(x+1, y+1)
|
|
n.S = p2s(x, y+1)
|
|
n.SW = p2s(x-1, y+1)
|
|
n.W = p2s(x-1, y)
|
|
return n
|
|
end
|
|
|
|
local max = {y=0, x=0}
|
|
local min = {y=10000, x=10000}
|
|
function updateMaxMin( j, i )
|
|
if j>max.x then max.x = j
|
|
elseif j<min.x then min.x = j end
|
|
if i>max.y then max.y = i
|
|
elseif i<min.y then min.y = i end
|
|
end
|
|
|
|
local nelves = 0
|
|
local elves = {}
|
|
|
|
-- parse map
|
|
local i = 1
|
|
for line in io.lines() do
|
|
local j = 1
|
|
for c in string.gmatch(line, "%g") do
|
|
if c=="#" then
|
|
elves[ p2s(j,i) ] = true
|
|
updateMaxMin(j, i)
|
|
nelves = nelves + 1
|
|
end
|
|
j = j + 1
|
|
end
|
|
i = i + 1
|
|
end
|
|
|
|
|
|
local dirs = {"N", "S", "W", "E"}
|
|
local offdirs = 0
|
|
local round = 1
|
|
local result1
|
|
repeat
|
|
-- first half
|
|
local attempts = {}
|
|
for s, e in pairs(elves) do
|
|
local x, y = s2p(s)
|
|
|
|
local alone = true
|
|
local n = neighbors(x,y)
|
|
for k, ns in pairs(n) do
|
|
if elves[ns] then alone = false break end
|
|
end
|
|
if alone then goto continue end
|
|
|
|
for i=0,3 do
|
|
local idirs = (i+offdirs)%4 + 1
|
|
local dir = dirs[idirs]
|
|
if dir=="N" and not (elves[n.NW] or elves[n.N] or elves[n.NE]) then
|
|
--print("propose north")
|
|
if attempts[n.N] == nil then
|
|
attempts[n.N] = s
|
|
elseif attempts[n.N] then -- attempt
|
|
attempts[n.N] = false
|
|
end
|
|
break
|
|
elseif dir=="S" and not (elves[n.SW] or elves[n.S] or elves[n.SE]) then
|
|
--print("propose south")
|
|
if attempts[n.S] == nil then
|
|
attempts[n.S] = s
|
|
elseif attempts[n.S] then -- attempt
|
|
attempts[n.S] = false
|
|
end
|
|
break
|
|
elseif dir=="W" and not (elves[n.SW] or elves[n.W] or elves[n.NW]) then
|
|
--print("propose west")
|
|
if attempts[n.W] == nil then
|
|
attempts[n.W] = s
|
|
elseif attempts[n.W] then -- attempt
|
|
attempts[n.W] = false
|
|
end
|
|
break
|
|
elseif dir=="E" and not (elves[n.SE] or elves[n.E] or elves[n.NE]) then
|
|
-- print("propose east")
|
|
if attempts[n.E] == nil then
|
|
attempts[n.E] = s
|
|
elseif attempts[n.E] then -- attempt
|
|
attempts[n.E] = false
|
|
end
|
|
break
|
|
end
|
|
end
|
|
|
|
::continue::
|
|
end
|
|
|
|
--second half
|
|
local count = 0
|
|
for k, s in pairs(attempts) do
|
|
if s then
|
|
elves[s] = nil
|
|
elves[k] = true
|
|
local nx, ny = s2p(k)
|
|
updateMaxMin(nx, ny)
|
|
count = count + 1
|
|
end
|
|
end
|
|
|
|
--[[
|
|
print("moved:",count)
|
|
print(min.x, min.y, max.x, max.y)
|
|
--]]
|
|
|
|
offdirs = (offdirs==3) and 0 or (offdirs+1)
|
|
|
|
if round%100==0 then
|
|
print("round", round)
|
|
end
|
|
|
|
if round == 10 then
|
|
result1 = (max.y-min.y+1)*(max.x-min.x+1)-nelves
|
|
end
|
|
|
|
if count > 0 then
|
|
round = round + 1
|
|
end
|
|
until count == 0
|
|
|
|
print("part 1", result1)
|
|
print("part 2", round)
|
|
|
|
-- print map:
|
|
for y=min.y,max.y do
|
|
local m = ""
|
|
for x=min.x,max.x do
|
|
local s = p2s(x,y)
|
|
m = m .. (elves[s] and "#" or ".")
|
|
end
|
|
-- print(m)
|
|
end
|