summaryrefslogtreecommitdiff
path: root/24/1_1.lua
diff options
context:
space:
mode:
authorAlex Pickering <alex@cogarr.net>2025-02-07 12:49:48 -0600
committerAlex Pickering <alex@cogarr.net>2025-02-07 12:49:48 -0600
commit3555be54c2abb8d5ece008a60dbdfbde0ffbddd7 (patch)
tree278876284d07118ecdea5c48cb6453f3122887f0 /24/1_1.lua
downloadadvent_of_code_2022-3555be54c2abb8d5ece008a60dbdfbde0ffbddd7.tar.gz
advent_of_code_2022-3555be54c2abb8d5ece008a60dbdfbde0ffbddd7.tar.bz2
advent_of_code_2022-3555be54c2abb8d5ece008a60dbdfbde0ffbddd7.zip
inital commitHEADmaster
Diffstat (limited to '24/1_1.lua')
-rw-r--r--24/1_1.lua192
1 files changed, 192 insertions, 0 deletions
diff --git a/24/1_1.lua b/24/1_1.lua
new file mode 100644
index 0000000..586835a
--- /dev/null
+++ b/24/1_1.lua
@@ -0,0 +1,192 @@
+require "ext"
+local directions = {
+ right = {0,1},
+ down = {1,0},
+ left = {0,-1},
+ up = {-1,0},
+ wait = {0,0},
+}
+local tiles = {
+ wall = {rep="#"},
+ lbliz = {rep="<",move=directions.left},
+ rbliz = {rep=">",move=directions.right},
+ ubliz = {rep="^",move=directions.up},
+ dbliz = {rep="v",move=directions.down},
+ empty = {rep="."}
+}
+local map = {}
+local row,col = 0,0
+local start,finish
+local function place(map,row,col,ent)
+ map[row] = map[row] or {}
+ map[row][col] = map[row][col] or {}
+ table.insert(map[row][col],ent)
+end
+for line in io.lines() do
+ map[#map+1] = {}
+ row = row + 1
+ col = 0
+ for char in line:gmatch("(.)") do
+ col = col + 1
+ if char == "." then
+ if row == 1 then
+ start = col
+ else
+ finish = col
+ end
+ end
+ for name,tile in pairs(tiles) do
+ if char == tile.rep and name ~= "empty" then
+ place(map,row,col,{r=row,c=col,t=tile})
+ break
+ end
+ end
+ end
+end
+local w,h = col,row
+local function print_puzzle(map,flood)
+ for row = 1,h do
+ for col = 1,w do
+ if map[row] and map[row][col] then
+ local elist = map[row][col]
+ if #elist == 1 then
+ io.write(elist[1].t.rep .. " ")
+ else
+ io.write("* ")
+ end
+ else
+ if flood and flood[row] and flood[row][col] then
+ io.write(string.format("%-2d",flood[row][col]))
+ else
+ io.write(" ")
+ end
+ end
+ end
+ io.write("\n")
+ end
+end
+
+local h,w = #map, #map[1]
+local min_walk = math.abs(finish - start) + h
+
+print_puzzle(map)
+
+local function step_map(map)
+ local newmap = {}
+ for row = 1,h do
+ for col = 1,w do
+ if map[row] and map[row][col] then
+ for _, ent in pairs(map[row][col]) do
+ if ent.t.move then
+ local dir = ent.t.move
+ ent.r = ent.r + dir[1]
+ ent.c = ent.c + dir[2]
+ --loop
+ if ent.r == 1 then
+ ent.r = h-1
+ elseif ent.r == h then
+ ent.r = 2
+ elseif ent.c == 1 then
+ ent.c = w-1
+ elseif ent.c == w then
+ ent.c = 2
+ end
+ place(newmap,ent.r,ent.c,ent)
+ else
+ place(newmap,ent.r,ent.c,ent)
+ end
+ end
+ end
+ end
+ end
+ return newmap
+end
+local function could_move(map,row,col)
+ local ret = (
+ row >= 1 and
+ col > 1 and
+ row <= h and
+ col < w and
+ (map[row] == nil or
+ map[row][col] == nil or
+ map[row][col].t ~= tiles.wall)
+ )
+ --print(ret)
+ return ret
+end
+
+--map doesn't change, no matter what we do, we can store the blizzard simulation
+local map_mem, mapat = {}, {[0] = map}
+setmetatable(mapat,{__index=function(self,key)
+ if map_mem[key] then return map_mem[key] end
+ map_mem[key] = step_map(mapat[key-1])
+ return map_mem[key]
+end})
+
+local state = {
+ location = {1,start},
+ minute = 0,
+ speculative_goal = min_walk
+}
+local function copy_state(state)
+ return {
+ location = {state.location[1],state.location[2]},
+ minute = state.minute,
+ speculative_goal = state.speculative_goal
+ }
+end
+local spec_tbl = {
+ [directions.right] = -1,
+ [directions.down] = -1,
+ [directions.left] = 2,
+ [directions.up] = 2,
+ [directions.wait] = 0
+}
+local flood = {}
+for row = 1,h do
+ flood[row] = {}
+end
+flood[1][2] = 0
+local min = 0
+while flood[h][w-1] == nil do
+ min = min + 1
+ print("Min",min)
+ local nmap = mapat[min-1]
+ local toins = {}
+ --[[
+ print("Before flooding 1:")
+ print_puzzle(nmap,flood)
+ ]]
+ --flood outward
+ for rn,row in pairs(flood) do
+ for cn,col in pairs(row) do
+ if flood[rn][cn] then
+ for name, direction in pairs(directions) do
+ --print("Flooding",rn,cn,name)
+ local trow = rn + direction[1]
+ local tcol = cn + direction[2]
+ if could_move(nmap,trow,tcol) and flood[trow][tcol] == nil then
+ table.insert(toins,{trow,tcol})
+ end
+ end
+ end
+ end
+ end
+ for _,v in pairs(toins) do
+ flood[v[1]][v[2]] = min
+ end
+ --[[
+ print("After flooding 1:")
+ print_puzzle(nmap,flood)
+ ]]
+ nmap = mapat[min]
+ --clean up where blizzards pass
+ for rn,row in pairs(nmap) do
+ for cn, col in pairs(row) do
+ flood[rn][cn] = nil
+ end
+ end
+ print("After cleaning:")
+ print_puzzle(nmap,flood)
+end
+print(flood[h][w-1])