Declaratieve Talen/Oplossing Dijkstra Alternatief (Haskell): verschil tussen versies
Naar navigatie springen
Naar zoeken springen
Nieuwe pagina: ====Mogelijke oplossing==== alleen het kortste pad wordt niet terug gegeven, hiervoor zou je bij uw afbeelding moeten bijhouden van welke knoop de waarde afkomstig is, zodat je deze ... |
|||
Regel 1: | Regel 1: | ||
==== | ====Alternatieve oplossing (geeft pad en afstand terug) ==== | ||
<pre> | <pre> | ||
import List | import List | ||
data Afstand = | data Afstand = Afst Int | Inf deriving Show | ||
instance Eq Afstand where | |||
(Afst x) == (Afst y) = x == y | |||
Inf == _ = False | |||
_ == Inf = False | |||
instance Ord Afstand where | instance Ord Afstand where | ||
(Afst x) <= (Afst y) = x <= y | |||
Inf <= _ = False | |||
_ <= Inf = True | |||
_ <= | |||
------------------------------------------------------------------------ | |||
dijkstra :: String -> String -> (Afstand, String) | |||
dijkstra s e = | |||
let | |||
allknopen = knopen | |||
init = (Afst 0, s, s) : [(Inf, kn, "") | kn <- allknopen, kn /= s] | |||
tabel = dijkstra2 e allknopen init | |||
-- | |||
distance = getdistance e tabel | |||
path = findpath s e tabel | |||
in | |||
(distance, path) | |||
------------------------------------------------------------------------ | |||
--- Dijkstra algoritme: stel tabel op (Afstand, Punt, KortsteAfstandPunt) | |||
dijkstra2 :: String -> [String] -> [(Afstand, String, String)] -> [(Afstand, String, String)] | |||
dijkstra2 endknoop remknopen tabel = | |||
- | |||
let | let | ||
klknoop@(_, k, _) = zoek_kleinste remknopen tabel | |||
newremknopen = delete k remknopen | |||
newtable = updatetabel newremknopen klknoop tabel | |||
in | in | ||
if (k == endknoop) | |||
if ( | then | ||
then | newtable | ||
else dijkstra2 | else | ||
dijkstra2 endknoop newremknopen newtable | |||
updatetabel :: [String] -> (Afstand, String, String) -> [(Afstand, String, String)] -> [(Afstand, String, String)] | |||
updatetabel _ _ [] = [] | |||
updatetabel remknopen klknoop@(dmin, kmin, _) (currknoop@(dcurr, kcurr, _) : xs) = | |||
if | if (elem kcurr remknopen) | ||
then | then | ||
let | let | ||
newcurrknoop = getnewdist klknoop currknoop | |||
in | in | ||
newcurrknoop : updatetabel remknopen klknoop xs | |||
else | else | ||
currknoop : updatetabel remknopen klknoop xs | |||
getnewdist :: (Afstand, String, String) -> (Afstand, String, String) -> (Afstand, String, String) | |||
getnewdist (dmin, kmin, kminorig) orig@(dcurr, kcurr, kcurrorig) = | |||
let | let | ||
dnew = plusafstand dmin (boog kmin kcurr) | |||
--dnew = min dcurr drol | |||
in | in | ||
if dcurr < dnew | |||
then | |||
orig --(dcurr, kcurr, kcurrorig) | |||
plusafstand _ | else | ||
(dnew, kcurr, kmin) | |||
zoek_kleinste :: [String] -> [(String, | |||
plusafstand :: Afstand -> Afstand -> Afstand | |||
zoek_kleinste | plusafstand Inf _ = Inf | ||
if (elem | plusafstand _ Inf = Inf | ||
then | plusafstand (Afst x) (Afst y) = Afst (x + y) | ||
else (" | |||
zoek_kleinste | zoek_kleinste :: [String] -> [(Afstand, String, String)] -> (Afstand, String, String) | ||
zoek_kleinste remknopen [curr@(_, k, _)] = | |||
if (elem k remknopen) | |||
then | |||
curr | |||
else | |||
(Inf, "Error", "") | |||
zoek_kleinste remknopen (newcandid@(d0, k0, _) : xs) = | |||
let | let | ||
smallest@(d1, k1, _) = zoek_kleinste remknopen xs | |||
in | in | ||
if( | if (d0 < d1 && (elem k0 remknopen)) | ||
then (s, | then | ||
newcandid | |||
else | |||
smallest | |||
------------------------------------------------------------------------ | |||
--- Pad bepalen | |||
findpath :: String -> String -> [(Afstand, String, String)] -> String | |||
findpath s e table | s == e = s | |||
| otherwise = | |||
let | |||
nextkey = getnext table e | |||
in | |||
(findpath s nextkey table) ++ e | |||
getnext :: [(Afstand, String, String)] -> String -> String | |||
getnext ((_, key0, nextkey) : xs) key1 | key0 == key1 = nextkey | |||
| otherwise = getnext xs key1 | |||
------------------------------------------------------------------------ | |||
--- Afstand opzoeken in tabel | |||
getdistance :: String -> [(Afstand, String, String)] -> Afstand | |||
getdistance key1 ((dist, key0, _) : xs) | key0 == key1 = dist | |||
| otherwise = getdistance key1 xs | |||
------------------------------------------------------------------------ | |||
-- Geimproviseerde gegevens | |||
boog :: String -> String -> Afstand | |||
boog s e | dist s e < Inf = dist s e | |||
| otherwise = dist e s | |||
dist :: String -> String -> Afstand | |||
dist "a" "b" = Afst 1 | |||
dist "a" "c" = Afst 2 | |||
dist "a" "d" = Afst 10 | |||
dist "b" "c" = Afst 5 | |||
dist "c" "d" = Afst 1 | |||
dist _ _ = Inf | |||
knopen :: [String] | |||
knopen = ["a", "b", "c", "d"] | |||
</pre> | </pre> |
Huidige versie van 13 jan 2009 18:16
Alternatieve oplossing (geeft pad en afstand terug)
import List data Afstand = Afst Int | Inf deriving Show instance Eq Afstand where (Afst x) == (Afst y) = x == y Inf == _ = False _ == Inf = False instance Ord Afstand where (Afst x) <= (Afst y) = x <= y Inf <= _ = False _ <= Inf = True ------------------------------------------------------------------------ dijkstra :: String -> String -> (Afstand, String) dijkstra s e = let allknopen = knopen init = (Afst 0, s, s) : [(Inf, kn, "") | kn <- allknopen, kn /= s] tabel = dijkstra2 e allknopen init -- distance = getdistance e tabel path = findpath s e tabel in (distance, path) ------------------------------------------------------------------------ --- Dijkstra algoritme: stel tabel op (Afstand, Punt, KortsteAfstandPunt) dijkstra2 :: String -> [String] -> [(Afstand, String, String)] -> [(Afstand, String, String)] dijkstra2 endknoop remknopen tabel = let klknoop@(_, k, _) = zoek_kleinste remknopen tabel newremknopen = delete k remknopen newtable = updatetabel newremknopen klknoop tabel in if (k == endknoop) then newtable else dijkstra2 endknoop newremknopen newtable updatetabel :: [String] -> (Afstand, String, String) -> [(Afstand, String, String)] -> [(Afstand, String, String)] updatetabel _ _ [] = [] updatetabel remknopen klknoop@(dmin, kmin, _) (currknoop@(dcurr, kcurr, _) : xs) = if (elem kcurr remknopen) then let newcurrknoop = getnewdist klknoop currknoop in newcurrknoop : updatetabel remknopen klknoop xs else currknoop : updatetabel remknopen klknoop xs getnewdist :: (Afstand, String, String) -> (Afstand, String, String) -> (Afstand, String, String) getnewdist (dmin, kmin, kminorig) orig@(dcurr, kcurr, kcurrorig) = let dnew = plusafstand dmin (boog kmin kcurr) --dnew = min dcurr drol in if dcurr < dnew then orig --(dcurr, kcurr, kcurrorig) else (dnew, kcurr, kmin) plusafstand :: Afstand -> Afstand -> Afstand plusafstand Inf _ = Inf plusafstand _ Inf = Inf plusafstand (Afst x) (Afst y) = Afst (x + y) zoek_kleinste :: [String] -> [(Afstand, String, String)] -> (Afstand, String, String) zoek_kleinste remknopen [curr@(_, k, _)] = if (elem k remknopen) then curr else (Inf, "Error", "") zoek_kleinste remknopen (newcandid@(d0, k0, _) : xs) = let smallest@(d1, k1, _) = zoek_kleinste remknopen xs in if (d0 < d1 && (elem k0 remknopen)) then newcandid else smallest ------------------------------------------------------------------------ --- Pad bepalen findpath :: String -> String -> [(Afstand, String, String)] -> String findpath s e table | s == e = s | otherwise = let nextkey = getnext table e in (findpath s nextkey table) ++ e getnext :: [(Afstand, String, String)] -> String -> String getnext ((_, key0, nextkey) : xs) key1 | key0 == key1 = nextkey | otherwise = getnext xs key1 ------------------------------------------------------------------------ --- Afstand opzoeken in tabel getdistance :: String -> [(Afstand, String, String)] -> Afstand getdistance key1 ((dist, key0, _) : xs) | key0 == key1 = dist | otherwise = getdistance key1 xs ------------------------------------------------------------------------ -- Geimproviseerde gegevens boog :: String -> String -> Afstand boog s e | dist s e < Inf = dist s e | otherwise = dist e s dist :: String -> String -> Afstand dist "a" "b" = Afst 1 dist "a" "c" = Afst 2 dist "a" "d" = Afst 10 dist "b" "c" = Afst 5 dist "c" "d" = Afst 1 dist _ _ = Inf knopen :: [String] knopen = ["a", "b", "c", "d"]