3
3
4
4
import Data.Map qualified as M
5
5
import Data.Set qualified as S
6
- import Data.Maybe (fromJust )
6
+ import Data.Maybe (fromJust , fromMaybe )
7
7
import Data.Sequence (Seq (.. ), fromList , (><) )
8
8
9
9
main :: IO ()
@@ -14,7 +14,7 @@ main = interact $ unlines . demo . parse
14
14
dbfs grid = bfs grid (0 , 0 ) (visitor " bfs" )
15
15
dsp grid = let end = maxNode grid
16
16
(r, zs) = dijkstra grid (0 , 0 ) end (visitor " shortest-path" )
17
- in zs ++ [" shortest-path result " ++ show r ]
17
+ in zs ++ [" shortest-path result " ++ ( show $ fromMaybe ( - 1 ) r) ]
18
18
19
19
type Node = (Int , Int )
20
20
data Grid a = Grid { items :: M. Map Node a , maxNode :: Node } deriving Show
@@ -52,6 +52,30 @@ bfs grid@Grid { items } start visitor = go (Empty :|> start) S.empty
52
52
go (xs :|> x) seen = visit x : go ys (S. insert x seen)
53
53
where ys = (fromList $ neighbours grid x) >< xs
54
54
55
+ -- For our example, the weight of the edge between u and v is the value
56
+ -- at v. But this can be any arbitrary function or input data.
57
+ distance :: Grid Int -> Node -> Node -> Int
58
+ distance Grid { items } u v = fromJust $ M. lookup v items
59
+
55
60
-- Find the shortest path from start, to end, using Dijkstra's algorithm.
56
- dijkstra :: Grid a -> Node -> Node -> (Node -> a -> b ) -> (Int , [b ])
57
- dijkstra grid@ Grid { items } start end visitor = (0 , [] )
61
+ dijkstra :: Grid Int -> Node -> Node -> (Node -> Int -> b ) -> (Maybe Int , [b ])
62
+ dijkstra grid@ Grid { items } start end visitor = go (M. singleton start 0 ) S. empty
63
+ where
64
+ visit x = let item = fromJust $ M. lookup x items in visitor x item
65
+ next ds seen = (M. lookupMin $ M. withoutKeys ds seen)
66
+ go ds seen = case next ds seen of
67
+ Nothing -> (Nothing , [] )
68
+ Just (u, du)
69
+ | u == end -> (M. lookup u ds, [visit u])
70
+ | otherwise ->
71
+ let v = visit u
72
+ seen' = S. insert u seen
73
+ ds' = foldl (relax u du) ds (neighbours grid u)
74
+ (d', vs) = go ds' seen'
75
+ in (d', v : vs)
76
+
77
+ relax :: Node -> Int -> M. Map Node Int -> Node -> M. Map Node Int
78
+ relax u du ds v = let d = distance grid u v in case M. lookup v ds of
79
+ Just dv | dv < du + d -> ds
80
+ _ -> M. insert v (du + d) ds
81
+
0 commit comments