F #, not very short (72 non-empty lines), but readable. I slightly modified / honed the specification; I assume that the original labyrinth is a rectangle completely surrounded by walls, I use different characters (which do not damage my eyes), I allow orthogonal movements (not diagonal). I tried only one sample of the maze. Except for the error about the x and y pointers, this worked for the first time, so I expect it to be correct (I did nothing to check it, except for the eyeball, the solution is on the same sample that I gave it).
open System [<Literal>] let WALL = '#' [<Literal>] let OPEN = ' ' [<Literal>] let START = '^' [<Literal>] let END = '$' [<Literal>] let WALK = '.' let sampleMaze = @"############### # # # # # ^# # # ### # # # # # # # # # # # # ############ # # $ # ###############" let lines = sampleMaze.Split([|'\r';'\n'|], StringSplitOptions.RemoveEmptyEntries) let width = lines |> Array.map (fun l -> l.Length) |> Array.max let height = lines.Length type BestInfo = (int * int) list * int // path to here, num steps let bestPathToHere : BestInfo option [,] = Array2D.create width height None let mutable startX = 0 let mutable startY = 0 for x in 0..width-1 do for y in 0..height-1 do if lines.[y].[x] = START then startX <- x startY <- y bestPathToHere.[startX,startY] <- Some([],0) let q = new System.Collections.Generic.Queue<_>() q.Enqueue((startX,startY)) let StepTo newX newY (path,count) = match lines.[newY].[newX] with | WALL -> () | OPEN | START | END -> match bestPathToHere.[newX,newY] with | None -> bestPathToHere.[newX,newY] <- Some((newX,newY)::path,count+1) q.Enqueue((newX,newY)) | Some(_,oldCount) when oldCount > count+1 -> bestPathToHere.[newX,newY] <- Some((newX,newY)::path,count+1) q.Enqueue((newX,newY)) | _ -> () | c -> failwith "unexpected maze char: '%c'" c while not(q.Count = 0) do let x,y = q.Dequeue() let (Some(path,count)) = bestPathToHere.[x,y] StepTo (x+1) (y) (path,count) StepTo (x) (y+1) (path,count) StepTo (x-1) (y) (path,count) StepTo (x) (y-1) (path,count) let mutable endX = 0 let mutable endY = 0 for x in 0..width-1 do for y in 0..height-1 do if lines.[y].[x] = END then endX <- x endY <- y printfn "Original maze:" printfn "%s" sampleMaze let bestPath, bestCount = bestPathToHere.[endX,endY].Value printfn "The best path takes %d steps." bestCount let resultMaze = Array2D.init width height (fun xy -> lines.[y].[x]) bestPath |> List.tl |> List.iter (fun (x,y) -> resultMaze.[x,y] <- WALK) for y in 0..height-1 do for x in 0..width-1 do printf "%c" resultMaze.[x,y] printfn "" //Output: //Original maze: //
source share