require "ext" local parse_map = true local map = {} local row,col = 0,0 local start local commands = {} local face_size = 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 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 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 mem_loop = {} local function find_loop_loc(sloc, direction) print("Finding loop location from",sloc,"dir",direction) if mem_loop[sloc] and mem_loop[sloc][direction] then return mem_loop[sloc][direction] end local srow, scol = sloc:match("(%d+),(%d+)") local radd, cadd = -direction[1], -direction[2] while map[string.format("%d,%d",srow,scol)] ~= nil do print("Examining",string.format("%d,%d",srow,scol),"was not nil") srow, scol = srow + radd, scol + cadd end print("Examining",string.format("%d,%d",srow,scol),"was nil") local ret = string.format("%d,%d",srow + direction[1],scol + direction[2]) mem_loop[ret] = mem_loop[ret] or {} mem_loop[ret][direction] = ret print("Returning",ret) return ret end print("map",map) print("commands",commands) local state = { location = start, direction = 0 } print("Starting state:",state) local function open(location,direction) local crow, ccol = state.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 true, rloc elseif map[rloc] == false then return false else local loop_loc = find_loop_loc(location,direction) assert(map[loop_loc] ~= nil) if map[loop_loc] then return true, loop_loc else return false end end end local function run(state, instructions) local function walk(state,n) for i = 1, n do local dir = directions[dirmap[state.direction].name] local isopen, newloc = open(state.location,dir) if isopen then print("Walked to",newloc) state.location = newloc else break end end end local function turn(state,dir) 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 run(state,commands) print(state) local row, col = state.location:match("(%d+),(%d+)") print((row*1000) + (col * 4) + state.direction)