summaryrefslogtreecommitdiff
path: root/22/2.lua
diff options
context:
space:
mode:
Diffstat (limited to '22/2.lua')
-rw-r--r--22/2.lua358
1 files changed, 358 insertions, 0 deletions
diff --git a/22/2.lua b/22/2.lua
new file mode 100644
index 0000000..769e0e8
--- /dev/null
+++ b/22/2.lua
@@ -0,0 +1,358 @@
+require "ext"
+local parse_map = true
+local map = {}
+local row,col = 0,0
+ local start
+ local commands = {}
+
+ local function parse_command(line)
+ local commands = {}
+ local ccursor = line
+ while ccursor ~= "" do
+ if ccursor:find("^%d") then
+ table.insert(commands,{type="walk",n=ccursor:match("^(%d+)")})
+ ccursor = ccursor:gsub("^(%d+)","")
+ elseif ccursor:find("^[LR]") then
+ table.insert(commands,{type="turn",n=ccursor:match("^([LR])")})
+ ccursor = ccursor:gsub("^[LR]","")
+ end
+ end
+ return commands
+end
+
+for line in io.lines() do
+ row = row + 1
+ if line ~= "" and parse_map then
+ col = 0
+ for char in line:gmatch("(.)") do
+ col = col + 1
+ local locf = string.format("%d,%d",row,col)
+ if char == "." then
+ if start == nil then
+ start = locf
+ end
+ map[locf] = true
+ elseif char == "#" then
+ map[locf] = false
+ end --else, it's nil
+ end
+ elseif line == "" and parse_map then
+ parse_map = false
+ elseif not parse_map then
+ commands = parse_command(line)
+ end
+end
+
+local directions = {
+ up = {-1, 0},
+ down = {1,0},
+ left = {0,-1},
+ right = {0,1}
+}
+local dirmap = {
+ [0] = {
+ name = "right",
+ R = 1,
+ L = 3
+ },
+ [1] = {
+ name = "down",
+ R = 2,
+ L = 0
+ },
+ [2] = {
+ name = "left",
+ R = 3,
+ L = 1
+ },
+ [3] = {
+ name = "up",
+ R = 0,
+ L = 2
+ }
+}
+local dirnames = {
+ [directions.up] = "up",
+ [directions.down] = "down",
+ [directions.left] = "left",
+ [directions.right] = "right"
+}
+local rev_dirmap = {}
+for i,t in pairs(dirmap) do
+ rev_dirmap[t.name] = i
+end
+
+
+local mem_loop = {}
+--Planning:
+-- 6 <-> 7
+-- 5 <-> 9
+-- 13 <-> 12
+--
+-- 1 <-> 11
+-- 2 <-> 14
+-- 4 <-> 10
+-- 8 <-> 3
+local function find_loop_loc(sloc, direction)
+ print("Finding loop location from",sloc,"dir",dirnames[direction])
+ --[[
+ if mem_loop[sloc] and mem_loop[sloc][direction] then
+ return mem_loop[sloc][direction][1], mem_loop[sloc][direction][2]
+ end
+ ]]
+ local srow, scol = sloc:match("(%d+),(%d+)")
+ srow, scol = tonumber(srow),tonumber(scol)
+ --just hard-code looping rules
+ local rloc, rdir
+ if srow == 1 and scol > 50 and scol <= 100 and direction == directions.up then -- 1 -> 11
+ print("1->11")
+ rloc = string.format("%d,%d",100+scol,1)
+ rdir = rev_dirmap.right
+ elseif scol == 1 and srow > 150 and srow <= 200 and direction == directions.left then -- 11 -> 1
+ print("11->1")
+ rloc = string.format("%d,%d",1,srow - 100)
+ rdir = rev_dirmap.down
+ elseif srow == 1 and scol > 100 and scol <= 150 and direction == directions.up then -- 2 -> 14
+ print("2->14")
+ rloc = string.format("%d,%d", 200, scol - 100)
+ rdir = rev_dirmap.up
+ elseif srow == 200 and scol > 0 and scol <= 50 and direction == directions.down then -- 14 ->2
+ print("14->2")
+ rloc = string.format("%d,%d", 1, scol + 100)
+ rdir = rev_dirmap.down
+ elseif scol == 51 and srow > 0 and srow <= 50 and direction == directions.left then -- 3 -> 8
+ print("3->8")
+ rloc = string.format("%d,%d", (50 - srow) + 101, 1)
+ rdir = rev_dirmap.right
+ elseif scol == 1 and srow > 100 and srow <= 150 and direction == directions.left then -- 8 -> 3
+ print("8->3")
+ rloc = string.format("%d,%d", ((150 - srow) - 100) + 101, 51)
+ rdir = rev_dirmap.right
+ elseif scol == 150 and srow > 0 and srow <= 100 and direction == directions.right then -- 4 -> 10
+ print("4->10")
+ rloc = string.format("%d,%d", (50 - srow) + 101, 100)
+ rdir = rev_dirmap.left
+ elseif scol == 100 and srow > 100 and srow <= 150 and direction == directions.right then -- 10 -> 4
+ print("10->4")
+ rloc = string.format("%d,%d", (151 - srow), 150)
+ rdir = rev_dirmap.left
+ elseif scol == 51 and srow > 50 and srow <= 100 and direction == directions.left then -- 5 -> 9
+ print("5->9")
+ rloc = string.format("%d,%d", 101, srow-50)
+ rdir = rev_dirmap.down
+ elseif srow == 101 and scol > 0 and scol <= 50 and direction == directions.up then -- 9 -> 5
+ print("9->5")
+ rloc = string.format("%d,%d", scol + 50, 51)
+ rdir = rev_dirmap.right
+ elseif srow == 50 and scol > 100 and scol <= 150 and direction == directions.down then -- 6 -> 7
+ print("6->7")
+ rloc = string.format("%d,%d", scol - 50, 100)
+ rdir = rev_dirmap.left
+ elseif scol == 100 and srow > 50 and srow <= 100 and direction == directions.right then -- 7 -> 6
+ print("7->6")
+ rloc = string.format("%d,%d", 50, srow + 50)
+ rdir = rev_dirmap.up
+ elseif srow == 150 and scol > 50 and scol <= 100 and direction == directions.down then -- 12 -> 13
+ print("12->13")
+ rloc = string.format("%d,%d", scol + 100, 50)
+ rdir = rev_dirmap.left
+ elseif scol == 50 and srow > 150 and srow <= 200 and direction == directions.right then -- 13 -> 12
+ print("13->12")
+ rloc = string.format("%d,%d", 150, srow - 100)
+ rdir = rev_dirmap.up
+ else
+ error(string.format("Unknown location + direction: %d,%d %s",srow, scol, tostring(direction)))
+ end
+ print("Returning",rloc,rdir)
+ assert(rloc)
+ assert(rdir)
+ assert(map[rloc] ~= nil)
+
+ mem_loop[rloc] = mem_loop[rloc] or {}
+ mem_loop[rloc][direction] = {rloc,rdir}
+ return rloc, rdir
+end
+
+print(map)
+local state = {
+ location = start,
+ direction = 0
+}
+print("Starting state:",state)
+
+local function open(location,direction)
+ local crow, ccol = location:match("(%d+),(%d+)")
+ local rrow, rcol = crow + direction[1], ccol + direction[2]
+ local rloc = string.format("%d,%d",rrow,rcol)
+ if map[rloc] then
+ return rloc, rev_dirmap[dirnames[direction]]
+ elseif map[rloc] == false then
+ return false
+ else
+ local loop_loc,newdir = find_loop_loc(location,direction)
+ assert(map[loop_loc] ~= nil)
+ if map[loop_loc] then
+ return loop_loc,newdir
+ else
+ return false
+ end
+ end
+end
+
+-- temporary function to test our cube is put togeather correctly
+local function exists(location,direction)
+ assert(type(location) == "string")
+ assert(type(direction) == "table")
+ print("Exists",location,dirnames[direction])
+ local crow, ccol = location:match("(%d+),(%d+)")
+ local rrow, rcol = crow + direction[1], ccol + direction[2]
+ local rloc = string.format("%d,%d",rrow,rcol)
+ print("checking existance of",rloc)
+ if map[rloc] ~= nil then
+ print("Exists in map")
+ return rloc,rev_dirmap[dirnames[direction]]
+ else
+ print("Looping around")
+ local loop_loc,newdir = find_loop_loc(location,direction)
+ assert(map[loop_loc] ~= nil)
+ assert(type(newdir) == "number")
+ return loop_loc,newdir
+ end
+
+end
+
+local corners = {
+ {1,51, directions.up},
+ {1,100, directions.right},
+ {50,51},
+ {50,100},
+ {50,101},
+ {51,51},
+ {51,100},
+ {101,1},
+ {101,50},
+ {101,51},
+ {101,100},
+ {150,1},
+ {150,50},
+ {150,51},
+ {150,100},
+ {200,1},
+ {200,50}
+}
+local edges = {
+
+}
+
+--[[
+-- test find_loop_loc, at each of our box corners, move around and make sure we end up back where we started
+for _, corner in pairs(corners) do
+
+ print("Checking counter-clockwise",corner)
+ -- counter-clockwise
+ local s,d = corner, directions.up
+ local ns, nd = exists(s,d)
+ print("Returns from exists 1:",ns,nd)
+ s = assert(e)
+ d = directions[dirmap[d].L]
+ e, d = exists(u,d)
+ s = assert(e)
+ d = directions[dirmap[d].L]
+ e, d = exists(u,d)
+ s = assert(e)
+ assert(s == corner,s .. " was not " .. corner)
+end
+]]
+
+local function run(state, instructions)
+ local function walk(state,n)
+ print("Walking",state,n)
+ for i = 1, n do
+ local dir = directions[dirmap[state.direction].name]
+ local newloc, newdir = open(state.location,dir)
+ --local newloc, newdir = exists(state.location,dir)
+ if newloc then
+ print("Walked to",newloc)
+ state.location = newloc
+ state.direction = newdir
+ else
+ break
+ end
+ end
+ end
+ local function turn(state,dir)
+ print("Turning",state)
+ assert(type(state.location) == "string")
+ assert(type(state.direction) == "number")
+ state.direction = dirmap[state.direction][dir]
+ end
+ while #instructions > 0 do
+ local ins = table.remove(instructions,1)
+ if ins.type == "walk" then
+ walk(state,ins.n)
+ elseif ins.type == "turn" then
+ turn(state,ins.n)
+ end
+ end
+end
+-- test that it works
+local ghosts = {
+ {1,51,rev_dirmap.up,"1L1L1"},
+ {1,51,rev_dirmap.left,"1R1R1"},
+ {1,100,rev_dirmap.up,"1R1R1"},
+ {1,100,rev_dirmap.right,"1L1L1"},
+ {1,101,rev_dirmap.up,"1L1L1"},
+ {1,101,rev_dirmap.left,"1R1R1"},
+ {1,150,rev_dirmap.up,"1R1R1"},
+ {1,150,rev_dirmap.right,"1L1L1"},
+ {50,51,rev_dirmap.left,"1L1L1"},
+ {50,51,rev_dirmap.down,"1R1R1"},
+ {50,100,rev_dirmap.right,"1R1R1"},
+ {50,100,rev_dirmap.down,"1L1L1"},
+ {50,150,rev_dirmap.right,"1R1R1"},
+ {50,150,rev_dirmap.down,"1L1L1"},
+ {51,51,rev_dirmap.left,"1R1R1"},
+ {51,51,rev_dirmap.up,"1L1L1"},
+ {51,100,rev_dirmap.up,"1R1R1"},
+ {51,100,rev_dirmap.right,"1L1L1"},
+ {100,51,rev_dirmap.left,"1L1L1"},
+ {100,51,rev_dirmap.down,"1R1R1"},
+ {100,100,rev_dirmap.right,"1R1R1"},
+ {100,100,rev_dirmap.down,"1L1L1"},
+ {101,1,rev_dirmap.up,"1L1L1"},
+ {101,1,rev_dirmap.left,"1R1R1"},
+ {101,50,rev_dirmap.up,"1R1R1"},
+ {101,50,rev_dirmap.right,"1L1L1"},
+ {101,51,rev_dirmap.left,"1R1R1"},
+ {101,51,rev_dirmap.up,"1L1L1"},
+ {101,100,rev_dirmap.right,"1L1L1"},
+ {101,100,rev_dirmap.up,"1R1R1"},
+ {150,1,rev_dirmap.left,"1L1L1"},
+ {150,1,rev_dirmap.down,"1R1R1"},
+ {150,50,rev_dirmap.right,"1R1R1"},
+ {150,50,rev_dirmap.down,"1L1L1"},
+ {150,51,rev_dirmap.left,"1L1L1"},
+ {150,51,rev_dirmap.down,"1R1R1"},
+ {150,100,rev_dirmap.right,"1R1R1"},
+ {150,100,rev_dirmap.down,"1L1L1"}
+}
+--[[
+for _,ghost in pairs(ghosts) do
+ print("=========================")
+ print("Checking location:",ghost)
+ local c = parse_command(ghost[4])
+ local locc = string.format("%d,%d",ghost[1],ghost[2])
+ local istate = {
+ location = locc,
+ direction = ghost[3]
+ }
+ run(istate,c)
+ assert(istate.location == locc)
+end
+os.exit(0)
+]]
+
+run(state,commands)
+print(state)
+local row, col = state.location:match("(%d+),(%d+)")
+print((row*1000) + (col * 4) + state.direction)