day 23
This commit is contained in:
parent
9c96d30ea6
commit
3a13913e74
153
day23/part1.lua
Executable file
153
day23/part1.lua
Executable file
@ -0,0 +1,153 @@
|
||||
#!/usr/bin/env luajit
|
||||
require("utils")
|
||||
|
||||
local targets = { A=3, B=5, C=7, D=9 }
|
||||
local costs = { A=1, B=10, C=100, D=1000 }
|
||||
|
||||
local f = io.open(arg[3])
|
||||
local line = f:read("*l") -- #####
|
||||
line = f:read("*l") -- #...#
|
||||
local hall = {}
|
||||
local length = #line - 2
|
||||
line = f:read("*l") -- ##A#B##
|
||||
local rooms = {}
|
||||
local depth = 1
|
||||
local ncorrect = 0
|
||||
while line do
|
||||
local l = 0
|
||||
for char in chars(line) do
|
||||
if char ~= "#" and char ~= " " then
|
||||
if rooms[l] == nil then rooms[l] = {} end
|
||||
table.insert(rooms[l], char)
|
||||
if targets[char] == l then ncorrect = ncorrect + 1 end
|
||||
end
|
||||
l = l + 1
|
||||
end
|
||||
line = f:read("*l") -- ##A#B##
|
||||
depth = depth + 1
|
||||
end
|
||||
depth = depth - 2
|
||||
|
||||
function printit()
|
||||
for l = 1, length do io.write(hall[l] or ".") end
|
||||
io.write("\n")
|
||||
for d = 1, depth do
|
||||
for l = 1, length do
|
||||
if rooms[l] then
|
||||
io.write(rooms[l][d] or ".")
|
||||
else
|
||||
io.write(" ")
|
||||
end
|
||||
end
|
||||
io.write("\n")
|
||||
end
|
||||
end
|
||||
|
||||
printit()
|
||||
|
||||
function addtoroom(rooms, room, char)
|
||||
local room = rooms[room]
|
||||
for d = depth, 1, -1 do
|
||||
if room[d] == nil then
|
||||
room[d] = char
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function removefromroom(rooms, i)
|
||||
local room = rooms[i]
|
||||
if room[1] == nil then
|
||||
if room[2] == nil then
|
||||
return
|
||||
else
|
||||
local c = room[2]
|
||||
room[2] = nil
|
||||
return c, 2, targets[c] == i
|
||||
end
|
||||
else
|
||||
local c = room[1]
|
||||
room[1] = nil
|
||||
return c, 1, targets[c] == i and targets[room[2]] == i
|
||||
end
|
||||
end
|
||||
|
||||
function pathtoroom(l, c, hall, rooms)
|
||||
local t = targets[c]
|
||||
if rooms[t][1] ~= nil then return end
|
||||
for p = l + sign(t - l), t, sign(t - l) do
|
||||
if hall[p] ~= nil then return end
|
||||
end
|
||||
local room = rooms[t]
|
||||
if room[2] == nil and room[1] == nil then
|
||||
return t, math.abs(t - l) + 2
|
||||
elseif room[2] == c and room[1] == nil then
|
||||
return t, math.abs(t - l) + 1
|
||||
end
|
||||
end
|
||||
|
||||
local nhall = 0
|
||||
local minscore = math.huge
|
||||
-- global: length, depth, hall, rooms, ncorrect, nhall, minscore
|
||||
-- returns: score
|
||||
function backtrack(step, score)
|
||||
-- print(step)
|
||||
-- printit()
|
||||
if step > 16 then
|
||||
elseif ncorrect == 8 and score < minscore then
|
||||
minscore = score
|
||||
print(minscore)
|
||||
elseif score > minscore then
|
||||
else
|
||||
-- move into rooms
|
||||
for l = 1, length do
|
||||
if hall[l] ~= nil then
|
||||
local c = hall[l]
|
||||
local room, distance = pathtoroom(l, c, hall, rooms)
|
||||
if room then
|
||||
hall[l] = nil
|
||||
addtoroom(rooms, room, c)
|
||||
ncorrect = ncorrect + 1
|
||||
backtrack(step + 1, score + distance * costs[c])
|
||||
ncorrect = ncorrect - 1
|
||||
removefromroom(rooms, room)
|
||||
hall[l] = c
|
||||
end
|
||||
end
|
||||
end
|
||||
-- remove from rooms
|
||||
for l, room in pairs(rooms) do
|
||||
local c, distance, complete = removefromroom(rooms, l)
|
||||
if c ~= nil then
|
||||
if not complete then
|
||||
if targets[c] == l then ncorrect = ncorrect - 1 end
|
||||
-- left
|
||||
local t = l - 1
|
||||
while t >= 1 and hall[t] == nil do
|
||||
if rooms[t] == nil then
|
||||
hall[t] = c
|
||||
backtrack(step + 1, score + (distance + l - t) * costs[c])
|
||||
hall[t] = nil
|
||||
end
|
||||
t = t - 1
|
||||
end
|
||||
-- right
|
||||
local t = l + 1
|
||||
while t <= length and hall[t] == nil do
|
||||
if rooms[t] == nil then
|
||||
hall[t] = c
|
||||
backtrack(step + 1, score + (distance + t - l) * costs[c])
|
||||
hall[t] = nil
|
||||
end
|
||||
t = t + 1
|
||||
end
|
||||
if targets[c] == l then ncorrect = ncorrect + 1 end
|
||||
end
|
||||
addtoroom(rooms, l, c)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
backtrack(0, 0)
|
||||
print(minscore)
|
157
day23/part2.lua
Executable file
157
day23/part2.lua
Executable file
@ -0,0 +1,157 @@
|
||||
#!/usr/bin/env luajit
|
||||
require("utils")
|
||||
|
||||
local targets = { A=3, B=5, C=7, D=9 }
|
||||
local costs = { A=1, B=10, C=100, D=1000 }
|
||||
|
||||
local f = io.open(arg[3])
|
||||
local line = f:read("*l") -- #####
|
||||
line = f:read("*l") -- #...#
|
||||
local hall = {}
|
||||
local length = #line - 2
|
||||
line = f:read("*l") -- ##A#B##
|
||||
local rooms = {}
|
||||
local depth = 1
|
||||
local ncorrect = 0
|
||||
while line do
|
||||
local l = 0
|
||||
for char in chars(line) do
|
||||
if char ~= "#" and char ~= " " then
|
||||
if rooms[l] == nil then rooms[l] = {} end
|
||||
table.insert(rooms[l], char)
|
||||
if targets[char] == l then ncorrect = ncorrect + 1 end
|
||||
end
|
||||
l = l + 1
|
||||
end
|
||||
line = f:read("*l") -- ##A#B##
|
||||
depth = depth + 1
|
||||
end
|
||||
|
||||
table.insert(rooms[3], 2, "D")
|
||||
table.insert(rooms[3], 2, "D")
|
||||
table.insert(rooms[5], 2, "B"); ncorrect = ncorrect + 1 -- this line
|
||||
table.insert(rooms[5], 2, "C")
|
||||
table.insert(rooms[7], 2, "A")
|
||||
table.insert(rooms[7], 2, "B")
|
||||
table.insert(rooms[9], 2, "C")
|
||||
table.insert(rooms[9], 2, "A")
|
||||
|
||||
function printit()
|
||||
for l = 1, length do io.write(hall[l] or ".") end
|
||||
io.write("\n")
|
||||
for d = 1, depth do
|
||||
for l = 1, length do
|
||||
if rooms[l] then
|
||||
io.write(rooms[l][d] or ".")
|
||||
else
|
||||
io.write(" ")
|
||||
end
|
||||
end
|
||||
io.write("\n")
|
||||
end
|
||||
end
|
||||
|
||||
printit()
|
||||
|
||||
function addtoroom(rooms, room, char)
|
||||
local room = rooms[room]
|
||||
for d = depth, 1, -1 do
|
||||
if room[d] == nil then
|
||||
room[d] = char
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function removefromroom(rooms, i)
|
||||
local room = rooms[i]
|
||||
local c, dst, complete = nil, nil, true
|
||||
for d = depth, 1, -1 do
|
||||
if room[d] ~= nil then
|
||||
c, dst = room[d], d
|
||||
if targets[c] ~= i then complete = false end
|
||||
end
|
||||
end
|
||||
if dst then room[dst] = nil end
|
||||
return c, dst, complete
|
||||
end
|
||||
|
||||
function pathtoroom(l, c, hall, rooms)
|
||||
local t = targets[c]
|
||||
if rooms[t][1] ~= nil then return end
|
||||
for p = l + sign(t - l), t, sign(t - l) do
|
||||
if hall[p] ~= nil then return end
|
||||
end
|
||||
local room = rooms[t]
|
||||
for d = depth, 1, -1 do
|
||||
if room[d] == nil then
|
||||
return t, math.abs(t - l) + d
|
||||
elseif room[d] ~= c then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local nhall = 0
|
||||
local minscore = math.huge
|
||||
-- global: length, depth, hall, rooms, ncorrect, nhall, minscore
|
||||
-- returns: score
|
||||
function backtrack(step, score)
|
||||
if step > 32 then
|
||||
elseif ncorrect == 16 and score < minscore then
|
||||
minscore = score
|
||||
print(minscore)
|
||||
elseif score > minscore then
|
||||
else
|
||||
-- move into rooms
|
||||
for l = 1, length do
|
||||
if hall[l] ~= nil then
|
||||
local c = hall[l]
|
||||
local room, distance = pathtoroom(l, c, hall, rooms)
|
||||
if room then
|
||||
hall[l] = nil
|
||||
addtoroom(rooms, room, c)
|
||||
ncorrect = ncorrect + 1
|
||||
backtrack(step + 1, score + distance * costs[c])
|
||||
ncorrect = ncorrect - 1
|
||||
removefromroom(rooms, room)
|
||||
hall[l] = c
|
||||
end
|
||||
end
|
||||
end
|
||||
-- remove from rooms
|
||||
for l, room in pairs(rooms) do
|
||||
local c, distance, complete = removefromroom(rooms, l)
|
||||
if c ~= nil then
|
||||
if not complete then
|
||||
if targets[c] == l then ncorrect = ncorrect - 1 end
|
||||
-- left
|
||||
local t = l - 1
|
||||
while t >= 1 and hall[t] == nil do
|
||||
if rooms[t] == nil then
|
||||
hall[t] = c
|
||||
backtrack(step + 1, score + (distance + l - t) * costs[c])
|
||||
hall[t] = nil
|
||||
end
|
||||
t = t - 1
|
||||
end
|
||||
-- right
|
||||
local t = l + 1
|
||||
while t <= length and hall[t] == nil do
|
||||
if rooms[t] == nil then
|
||||
hall[t] = c
|
||||
backtrack(step + 1, score + (distance + t - l) * costs[c])
|
||||
hall[t] = nil
|
||||
end
|
||||
t = t + 1
|
||||
end
|
||||
if targets[c] == l then ncorrect = ncorrect + 1 end
|
||||
end
|
||||
addtoroom(rooms, l, c)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
backtrack(0, 0)
|
||||
print(minscore)
|
Loading…
Reference in New Issue
Block a user