Für meine Studien muss ich die folgende Funktion schreiben, die die kürzeste Route zwischen zwei Ländern bekommt. Ich habe bereits eine Funktion isRoute geschrieben, die prüft, ob es eine Verbindung zwischen zwei Ländern gibt, und eine Funktion yieldRoute, die nur eine Verbindung zwischen zwei Ländern zurückgibt. Jetzt muss ich eine Funktion codieren, die die kürzeste Route zwischen zwei Ländern zurückgibt.Wie man den Dijkstra-Algorithmus in Haskell implementiert
Meine erste Annäherung war, alle Verbindungen zwischen den zwei Ländern zu bekommen und dann die kürzeste zu bekommen, aber alle Verbindungen zu bekommen ist irgendwie nervig zu programmieren meiner Meinung nach. Jetzt komme ich auf die Idee, einen Dijstra-Algorithmus zu implementieren, aber ich finde das auch irgendwie schwer. Kannst du mir eine Idee geben, wie das geht?
Wir diese Art verwenden, haben
type Country = String
type Countries = [Country]
type TravelTime = Integer -- Travel time in minutes
data Connection = Air Country Country TravelTime
| Sea Country Country TravelTime
| Rail Country Country TravelTime
| Road Country Country TravelTime deriving (Eq,Ord,Show)
type Connections = [Connection]
data Itinerary = NoRoute | Route (Connections,TravelTime) deriving (Eq,Ord,Show)
Funktion Meine Ausbeute Route, die einfach Breitensuche ist (wir werden sie nicht mehr ändern, aber OFC wir neue Typen hinzufügen dürfen.): (Sry für Deutsch Kommentare)
-- Liefert eine Route falls es eine gibt
yieldRoute :: Connections -> Country -> Country -> Connections
yieldRoute cons start goal
| isRoute cons start goal == False = []
| otherwise = getRoute cons start [] [start] goal
getRoute :: Connections -> Country -> Connections -> Countries -> Country -> Connections
getRoute cons c gone visited target
| (c == target) = gone
| otherwise = if (visit cons c visited) then (getRoute cons (deeper cons c visited) (gone ++ get_conn cons c (deeper cons c visited)) (visited ++ [(deeper cons c visited)]) target) else (getRoute cons (back (drop (length gone -1) gone)) (take (length gone -1) gone) visited target)
-- Geht ein Land zurück
back :: Connections -> Country
back ((Air c1 c2 _):xs) = c1
back ((Sea c1 c2 _):xs) = c1
back ((Rail c1 c2 _):xs) = c1
back ((Road c1 c2 _):xs) = c1
-- Liefert das nächste erreichbare Country
deeper :: Connections -> Country -> Countries -> Country
deeper ((Air c1 c2 _):xs) c visited
| (c1 == c) = if (c2 `elem` visited) then (deeper xs c visited) else c2
| (c2 == c) = if (c1 `elem` visited) then (deeper xs c visited) else c1
| otherwise = deeper xs c visited
deeper ((Sea c1 c2 _):xs) c visited
| (c1 == c) = if (c2 `elem` visited) then (deeper xs c visited) else c2
| (c2 == c) = if (c1 `elem` visited) then (deeper xs c visited) else c1
| otherwise = deeper xs c visited
deeper ((Rail c1 c2 _):xs) c visited
| (c1 == c) = if (c2 `elem` visited) then (deeper xs c visited) else c2
| (c2 == c) = if (c1 `elem` visited) then (deeper xs c visited) else c1
| otherwise = deeper xs c visited
deeper ((Road c1 c2 _):xs) c visited
| (c1 == c) = if (c2 `elem` visited) then (deeper xs c visited) else c2
| (c2 == c) = if (c1 `elem` visited) then (deeper xs c visited) else c1
| otherwise = deeper xs c visited
-- Liefert eine Connection zwischen zwei Countries
get_conn :: Connections -> Country -> Country -> Connections
get_conn [] _ _ = error "Something went terribly wrong"
get_conn ((Air c1 c2 t):xs) c3 c4
| (c1 == c3) && (c2 == c4) = [(Air c1 c2 t)]
| (c1 == c4) && (c2 == c3) = [(Air c1 c2 t)]
| otherwise = get_conn xs c3 c4
get_conn ((Sea c1 c2 t):xs) c3 c4
| (c1 == c3) && (c2 == c4) = [(Air c1 c2 t)]
| (c1 == c4) && (c2 == c3) = [(Air c1 c2 t)]
| otherwise = get_conn xs c3 c4
get_conn ((Road c1 c2 t):xs) c3 c4
| (c1 == c3) && (c2 == c4) = [(Air c1 c2 t)]
| (c1 == c4) && (c2 == c3) = [(Air c1 c2 t)]
| otherwise = get_conn xs c3 c4
get_conn ((Rail c1 c2 t):xs) c3 c4
| (c1 == c3) && (c2 == c4) = [(Air c1 c2 t)]
| (c1 == c4) && (c2 == c3) = [(Air c1 c2 t)]
| otherwise = get_conn xs c3 c4
-- Überprüft ob eine besuchbare Connection exestiert
visit :: Connections -> Country -> Countries -> Bool
visit [] _ _ = False
visit ((Air c1 c2 _):xs) c visited
| (c1 == c) = if (c2 `elem` visited) then (visit xs c visited) else True
| (c2 == c) = if (c1 `elem` visited) then (visit xs c visited) else True
| otherwise = visit xs c visited
visit ((Sea c1 c2 _):xs) c visited
| (c1 == c) = if (c2 `elem` visited) then (visit xs c visited) else True
| (c2 == c) = if (c1 `elem` visited) then (visit xs c visited) else True
| otherwise = visit xs c visited
visit ((Rail c1 c2 _):xs) c visited
| (c1 == c) = if (c2 `elem` visited) then (visit xs c visited) else True
| (c2 == c) = if (c1 `elem` visited) then (visit xs c visited) else True
| otherwise = visit xs c visited
visit ((Road c1 c2 _):xs) c visited
| (c1 == c) = if (c2 `elem` visited) then (visit xs c visited) else True
| (c2 == c) = if (c1 `elem` visited) then (visit xs c visited) else True
Dieses habe ich jetzt schreiben:
yieldFastestRoute :: Connections -> Country -> Country -> Itinerary
Dijkst ra Algorithmus: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
Mein erster Ansatz war: (wie gesagt, ich Probleme mit der getallRoutes hatte)
yieldFastestRoute :: Connections -> Country -> Country -> Itinerary
yieldFastestRoute cons start targ
|(isRoute start targ == False) = NoRoute
|otherwise = (Route (getFastest (getAllRoutes cons start targ)) (sumTT (getFastest (getAllRoutes cons start targ))))
-- Liefert alle Routen zwischen zwei Ländern
getAllRoutes :: Connections -> Country -> Country -> [Connections]
-- Liefert aus einer Reihe von Connections die schnellste zurück
getFastest :: [Connections] -> Connections
getFastest (x:xs) = if ((sumTT x) < sumTT (getFastest xs) || null (getFastest xs)) then x else (getFastest xs)
sumTT :: Connections -> TravelTime
sumTT [] = 0
sumTT ((Air _ _ t): xs) = t ++ sumTT xs
sumTT ((Rail _ _ t): xs) = t ++ sumTT xs
sumTT ((Road _ _ t): xs) = t ++ sumTT xs
sumTT ((Sea _ _ t): xs) = t ++ sumTT xs
Ich mag im Grunde wissen, was ist der beste Weg, Dijkstra in Haskell zu implementieren, oder wenn Es gibt noch einen anderen Ansatz, dem ich folgen könnte.
1. Was ist der Dijkstra-Algorithmus? 2. Zeigen Sie uns Ihren Versuch, es zu implementieren. 3. Erklären Sie, welchen Teil der Implementierung Sie schwierig finden. – dave4420
Ich möchte, wenn es eine nicht extrem schwierige Möglichkeit ist, Dijstra in Haskell zu implementieren, oder wenn es einige leichtere approches zur Lösung des Problems gibt: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm –
Ich denke, diese Frage würde besser zu beantworten, wenn Sie sich fragen, wie Sie die entsprechenden Diagrammdatenstrukturen erstellen. danach sollte die Implementierung von Dijkstra nicht schwierig sein. Sie haben auch eine Menge Code und das ist ein bisschen schwer zu schlucken, speziell mit den deutschen Kommentaren – hugomg