module _81 open common open System open System.IO open System.Collections.Generic let testMatrix = [|"131,673,234,103,18"; "201,96,342,965,150"; "630,803,746,422,111"; "537,699,497,121,956"; "805,732,524,37,331"|] type Direction = | Down | Right | Init let coordMod f coord = function | Down -> (f (fst coord), snd coord) | Right -> (fst coord, f (snd coord)) | Init -> failwith "Ha" let coordDeref = coordMod ((-) 1) let coordRef = coordMod ((+) 1) let shortestDistance = let matrix = //File.ReadAllLines(@"81_matrix.txt") array2D (testMatrix |> Array.map strSplitInt) let mLen1, mLen2 = Array2D.length1 matrix, Array2D.length2 matrix let dist = Array2D.create mLen1 mLen2 Int32.MaxValue // let rec listInsert f v l = // match l with // | x::xs when f x -> v::x::xs // | x::xs -> x::listInsert f v xs // | [] -> [v] let rec f frontier = let expand coord = seq { let d, r = coordRef coord Down, coordRef coord Right let inMatrix coord = fst coord < mLen1 && snd coord < mLen2 let incl c = inMatrix c && dist.[fst c, snd c] = Int32.MaxValue if incl d then yield d if incl r then yield r } match frontier with | [] -> () | (coord,d)::xs -> dist.[fst coord, snd coord] <- d xs |> List.filter (fun ((c),_) -> c <> coord) |> List.append (expand coord |> Seq.map ( fun f -> let fd = matrix.[fst f, snd f] + d f,fd) |> List.ofSeq) |> List.sortWith (fun (_,d1) (_,d2) -> d1 - d2) |> f f [(0,0),matrix.[0,0]] dist.[mLen1 - 1, mLen2 - 1]