diff --git a/12023/16/16.lua b/12023/16/16.lua index da03df7..69794e3 100644 --- a/12023/16/16.lua +++ b/12023/16/16.lua @@ -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)