day 16, part 2!

This commit is contained in:
sejo 2023-12-16 08:34:17 +01:00
parent 1ef198fd5e
commit 20578ca8de
1 changed files with 113 additions and 68 deletions

View File

@ -12,50 +12,48 @@ for line in io.lines() do
local char = line:sub(c,c)
if char:match("[^%.]") then
map[r][c] = char
print(char, c,r)
end
end
r = r + 1
end
local height = r-1
print(width, height)
function coord(x,y)
return y*1000+x
end
function energize(x, y)
function energize(e,x, y)
local c = coord(x,y)
energized[c] = energized[c] and (energized[c]+1) or 1
e[c] = e[c] and (e[c]+1) or 1
end
function mark_energized(xo, yo, xf, yf)
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(xo,y)
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(x,yo)
energize(e,x,yo)
end
end
end
function count_energized()
function count_energized(e)
local count = 0
for c,v in pairs(energized) do
for c,v in pairs(e) do
count = count + 1
end
return count
end
function next_beams(xs,ys,dx,dy,char)
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
@ -93,15 +91,27 @@ function next_beams(xs,ys,dx,dy,char)
end
elseif char=="/" then --mirrors
if dx~=0 then
table.insert(beams, com(xs, ys-dx, 0, -dx))
ny = ys - dx
if ny>=1 and ny<=height then
table.insert(beams, com(xs, ny, 0, -dx))
end
elseif dy~=0 then
table.insert(beams, com(xs-dy, ys, -dy, 0))
nx = xs - dy
if nx>=1 and nx<=width then
table.insert(beams, com(nx, ys, -dy, 0))
end
end
elseif char=="\\" then
if dx~=0 then
table.insert(beams, com(xs, ys+dx, 0, dx))
ny = ys+dx
if ny>=1 and ny<=height then
table.insert(beams, com(xs, ny, 0, dx))
end
elseif dy~=0 then
table.insert(beams, com(xs+dy, ys, dy, 0))
nx = xs + dy
if nx>=1 and nx<=width then
table.insert(beams, com(nx, ys, dy, 0))
end
end
end
return beams
@ -110,64 +120,99 @@ end
com = table.pack
exp = table.unpack
energized = {}
local beams = {}
conditions = {}
table.insert(beams, com(1,1,1,0))
--table.insert(beams, com(3,9,-1,0))
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 charf = nil
--search next
if dx~= 0 then
local xm = x
local found = nil
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
charf = found
elseif dy~= 0 then
local ym = y
local found = nil
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
charf = found
end
print("found", charf, xf, yf)
-- mark energized
mark_energized(x,y,xf,yf)
local nb = next_beams(xf, yf, dx, dy, charf)
if nb then
for _, b in ipairs(nb) do
table.insert(beams, b)
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 charf = nil
--search next
if dx~= 0 then
local xm = x
local found = nil
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
charf = found
elseif dy~= 0 then
local ym = y
local found = nil
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
charf = found
end
end
until #beams==0
--print("found", charf, xf, yf)
-- mark energized
mark_energized(energized,x,y,xf,yf)
local nb = next_beams(xf, yf, dx, dy, charf, 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
--[[
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
print(s)
--]]
return count_energized(energized)
end
print("part 1", count_energized())
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)