129 lines
2.5 KiB
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)
|