Compare commits
3 Commits
9a95effede
...
14d3e749cd
Author | SHA1 | Date |
---|---|---|
sejo | 14d3e749cd | |
sejo | 20578ca8de | |
sejo | 1ef198fd5e |
|
@ -0,0 +1,192 @@
|
|||
io.input("input")
|
||||
|
||||
-- parse map
|
||||
local map = {}
|
||||
local r=1
|
||||
local width = 0
|
||||
for line in io.lines() do
|
||||
width = #line
|
||||
map[r] = {}
|
||||
for c=1,width do
|
||||
local char = line:sub(c,c)
|
||||
if char:match("[^%.]") then
|
||||
map[r][c] = char
|
||||
end
|
||||
end
|
||||
r = r + 1
|
||||
end
|
||||
local height = r-1
|
||||
|
||||
function coord(x,y)
|
||||
return y*1000+x
|
||||
end
|
||||
|
||||
function energize(e,x, y)
|
||||
local c = coord(x,y)
|
||||
e[c] = e[c] and (e[c]+1) or 1
|
||||
end
|
||||
|
||||
function mark_energized(e, xo, yo, xf, yf)
|
||||
if xo==xf then -- vertical
|
||||
yo, yf = math.min(yo,yf), math.max(yo,yf)
|
||||
yo = math.max(1,yo)
|
||||
yf = math.min(height, yf)
|
||||
for y=yo,yf do
|
||||
energize(e,xo,y)
|
||||
end
|
||||
elseif yo==yf then --horizontal
|
||||
xo, xf = math.min(xo, xf), math.max(xo, xf)
|
||||
xo = math.max(1,xo)
|
||||
xf = math.min(width, xf)
|
||||
for x=xo,xf do
|
||||
energize(e,x,yo)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function count_energized(e)
|
||||
local count = 0
|
||||
for c,v in pairs(e) do
|
||||
count = count + 1
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
function valid_beam(x, y, dx, dy)
|
||||
if x>=1 and x<=width and y>=1 and y<=height then
|
||||
return com(x,y,dx,dy)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function next_beams(xs,ys,dx,dy,char,conditions)
|
||||
if not char then return nil end
|
||||
local cond = table.concat(com(xs,ys,dx,dy),",")
|
||||
if conditions[cond] then return nil
|
||||
else conditions[cond] = true end
|
||||
|
||||
local beams = {}
|
||||
if char=="|" then -- splitters
|
||||
if dx~=0 then -- duplicate
|
||||
table.insert(beams, valid_beam(xs, ys+1, 0, 1))
|
||||
table.insert(beams, valid_beam(xs, ys-1, 0, -1))
|
||||
elseif dy~= 0 then -- passthrough
|
||||
table.insert(beams, valid_beam(xs, ys+dy, dx, dy))
|
||||
end
|
||||
elseif char=="-" then
|
||||
if dx~=0 then -- passthrough
|
||||
table.insert(beams, valid_beam(xs+dx, ys, dx, dy))
|
||||
elseif dy~= 0 then -- duplicate
|
||||
table.insert(beams, valid_beam(xs+1, ys, 1, 0))
|
||||
table.insert(beams, valid_beam(xs-1, ys, -1, 0))
|
||||
end
|
||||
elseif char=="/" then --mirrors
|
||||
if dx~=0 then
|
||||
table.insert(beams, valid_beam(xs, ys-dx, 0, -dx))
|
||||
elseif dy~=0 then
|
||||
table.insert(beams, valid_beam(xs-dy, ys, -dy, 0))
|
||||
end
|
||||
elseif char=="\\" then
|
||||
if dx~=0 then
|
||||
table.insert(beams, valid_beam(xs, ys+dx, 0, dx))
|
||||
elseif dy~=0 then
|
||||
table.insert(beams, com(xs+dy, ys, dy, 0))
|
||||
end
|
||||
end
|
||||
return beams
|
||||
end
|
||||
|
||||
com = table.pack
|
||||
exp = table.unpack
|
||||
|
||||
|
||||
function activate(x, y, dx, dy)
|
||||
local beams = {}
|
||||
local energized = {}
|
||||
local conditions = {}
|
||||
table.insert(beams, com(x,y,dx,dy))
|
||||
repeat
|
||||
local beam = table.remove(beams)
|
||||
local x,y,dx,dy = exp(beam)
|
||||
--print("\nbeam", x, y, dx, dy)
|
||||
local xf, yf = 0,0
|
||||
local found = nil
|
||||
--search next
|
||||
if dx~= 0 then
|
||||
local xm = x
|
||||
repeat
|
||||
if map[y][xm] then
|
||||
found = map[y][xm]
|
||||
else
|
||||
xm = xm + dx
|
||||
end
|
||||
until found or xm<1 or xm>width
|
||||
xf, yf = xm, y
|
||||
elseif dy~= 0 then
|
||||
local ym = y
|
||||
repeat
|
||||
if map[ym][x] then
|
||||
found = map[ym][x]
|
||||
else
|
||||
ym = ym + dy
|
||||
end
|
||||
until found or ym<1 or ym>height
|
||||
xf,yf = x,ym
|
||||
end
|
||||
|
||||
--print("found", found, xf, yf)
|
||||
-- mark energized
|
||||
mark_energized(energized,x,y,xf,yf)
|
||||
local nb = next_beams(xf, yf, dx, dy, found, conditions)
|
||||
if nb then
|
||||
for _, b in ipairs(nb) do
|
||||
table.insert(beams, b)
|
||||
end
|
||||
end
|
||||
until #beams==0
|
||||
|
||||
--[[
|
||||
for y=1,height do
|
||||
local s = ""
|
||||
for x=1,width do
|
||||
local char = energized[coord(x,y)] and "#" or "."
|
||||
s = s..char
|
||||
end
|
||||
print(s)
|
||||
end
|
||||
--]]
|
||||
return count_energized(energized)
|
||||
end
|
||||
|
||||
|
||||
print("part 1", activate(1,1,1,0))
|
||||
|
||||
local max = 0
|
||||
local max_conds = com(0,0,0,0)
|
||||
|
||||
-- from the top and bottom
|
||||
for x=1,width do
|
||||
local r = activate(x,1,0,1)
|
||||
if r>max then
|
||||
max, max_conds = r, com(x,1,0,1)
|
||||
end
|
||||
r = activate(x,height,0,-1)
|
||||
if r>max then
|
||||
max, max_conds = r, com(x,height,0,-1)
|
||||
end
|
||||
end
|
||||
|
||||
-- from the left and right
|
||||
for y=1,height do
|
||||
local r = activate(1,y,1,0)
|
||||
if r>max then
|
||||
max, max_conds = r, com(1,y,1,0)
|
||||
end
|
||||
r = activate(width,y,-1,0)
|
||||
if r>max then
|
||||
max, max_conds = r, com(width,y,-1,0)
|
||||
end
|
||||
end
|
||||
|
||||
print(table.concat(max_conds,","))
|
||||
print("part 2", max)
|
|
@ -0,0 +1,10 @@
|
|||
.|...\....
|
||||
|.-.\.....
|
||||
.....|-...
|
||||
........|.
|
||||
..........
|
||||
.........\
|
||||
..../.\\..
|
||||
.-.-/..|..
|
||||
.|....-|.\
|
||||
..//.|....
|
Loading…
Reference in New Issue