fork(2) download
  1. let solve maze =
  2. let maze = maze |> Seq.map Seq.toArray |> Seq.toArray
  3. let pos x =
  4. maze |> Seq.mapi (fun y m -> y, m)
  5. |> Seq.tryPick ((<||) (fun y -> Seq.tryFindIndex ((=) x) >> Option.map (fun x -> y, x)))
  6. let distance (y1, x1) (y2, x2) = abs (y1 - y2) + abs (x1 - x2)
  7. let rec solve goal cls = function
  8. | [] -> None
  9. | ((p, ds), _)::ops when p = goal -> ds |> List.rev |> String.concat "" |> Some
  10. | (((y, x), ds), (g, h)) as op::ops ->
  11. let cls = cls |> Map.add (y, x) op
  12. [(y - 1, x), "u"; (y + 1, x), "d"; (y, x - 1), "l"; (y, x + 1), "r"]
  13. |> List.choose (fun ((y, x) as p, d) ->
  14. if maze.[y].[x] <> '#' then Some((p, d::ds), (g + 1, distance goal p)) else None)
  15. |> List.fold (fun (cls, ops) (((p, _), (g, h)) as x) ->
  16. match Map.tryFind p cls with
  17. | Some(_, (cg, ch)) when g + h < cg + ch -> Map.remove p cls, x::ops
  18. | Some _ -> cls, ops
  19. | None -> cls, x::ops) (cls, ops)
  20. |> (fun (cls, ops) -> cls, ops |> Seq.sortBy (snd >> (<||) (+)) |> Seq.distinctBy (fst >> fst) |> Seq.toList)
  21. ||> solve goal
  22. match pos 'S', pos 'G' with
  23. | None, _ | _, None -> invalidArg "maze" "Either start or goal is not found."
  24. | Some start, Some goal -> solve goal Map.empty [(start, []), (0, distance start goal)]
  25.  
  26. Seq.initInfinite (fun _ -> System.Console.ReadLine()) |> Seq.takeWhile ((<>) "")
  27. |> solve |> printfn "%A"
  28.  
Success #stdin #stdout 0.26s 13376KB
stdin
#######
#..S..#
#.....#
#..G..#
#######

stdout
Some "dd"