From 3555be54c2abb8d5ece008a60dbdfbde0ffbddd7 Mon Sep 17 00:00:00 2001 From: Alex Pickering Date: Fri, 7 Feb 2025 12:49:48 -0600 Subject: inital commit --- 22/2.lua | 358 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 22/2.lua (limited to '22/2.lua') 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) -- cgit v1.2.3-70-g09d2