advent-of-code/12022/14/14.lua

129 lines
2.5 KiB
Lua

--io.input("test")
io.input("input")
function string2point( s )
local x, y = string.match( s, "(%d+),(%d+)" )
return { x=tonumber(x), y=tonumber(y) }
end
function coord2string( x, y )
return tostring(x) .. "," .. tostring(y)
end
map = {}
map.min = { x=1000, y=1000 }
map.max = { x=1, y=1 }
function map:updateRange( p )
local map = self
if p.x<map.min.x then map.min.x = p.x
elseif p.x>map.max.x then map.max.x = p.x
end
if p.y<map.min.y then map.min.y = p.y
elseif p.y>map.max.y then map.max.y = p.y
end
end
function map:fillWithRock( s1, s2 )
local map = self
local p1 = string2point( s1 )
local p2 = string2point( s2 )
map:updateRange( p1 )
map:updateRange( p2 )
if p1.x == p2.x then
local x = p1.x
local inc = (p1.y > p2.y) and -1 or 1
for y = p1.y, p2.y, inc do
local s = coord2string( x, y )
map[s] = "#"
end
elseif p1.y == p2.y then
local y = p1.y
local inc = (p1.x > p2.x) and -1 or 1
for x = p1.x, p2.x, inc do
local s = coord2string( x, y )
map[s] = "#"
end
end
end
function map:blocked( x, y )
local map = self
local s = coord2string( x, y )
return map[s] or y==map.max.y+2
end
function map:printArea( x1, y1, x2, y2 )
local map = self
print( map.min.x, map.min.y, map.max.x, map.max.y)
for row = y1, y2 do
local rs = ""
for col = x1, x2 do
local cs = coord2string( col, row )
local symbol = map[cs] or "."
rs = rs .. symbol
end
print( row, rs )
end
end
-- parse
for line in io.lines() do
local s1, s2
local i = 1
for point in string.gmatch( line, "(%d+,%d+)" ) do
s2 = point
if s1 then
map:fillWithRock( s1, s2 )
end
s1 = s2
i = i + 1
end
end
local result1, result2
local done = false
local i = 1
while not done do
local unit = { x=500, y=0 }
repeat
local moving = true
local nexty = unit.y+1
-- part 1
if nexty > map.max.y and not result1 then
result1 = i - 1
--done=true
end
if not map:blocked( unit.x, nexty ) then
unit.y = unit.y+1
elseif not map:blocked( unit.x-1, nexty ) then
unit.x = unit.x-1
unit.y = unit.y+1
elseif not map:blocked( unit.x+1, nexty) then
unit.x = unit.x+1
unit.y = unit.y+1
else
local s = coord2string( unit.x, unit.y )
map[s] = "o"
moving = false
-- part 2
if unit.y == 0 then
result2 = i
done = true
end
end
until not moving or done
i = i + 1
end
map:printArea( 490, 0, 503, 11 )
print("part 1", result1)
print("part 2", result2)