Skip to content

Commit 542f4ab

Browse files
bijoythomasegonSchiele
authored andcommitted
Added Haskell example for Dijkstras algorithm (egonSchiele#18)
* Adding binary search example for Haskell * Adding selection sort example in Haskell * Adding Haskell examples for chapter 3 * Adding examples for chapter 4 * Adding examples for chapter 5 * Adding git ignore * Add Haskell example for BFS * resetting * Adding haskell example for dijkstras algorithm * Adding Haskell example for chapter 8 * Adding power set based solution for set covering problem * Adding Haskell examples for chap 9
1 parent 1ab56fc commit 542f4ab

File tree

5 files changed

+248
-0
lines changed

5 files changed

+248
-0
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import Data.List
2+
import Control.Applicative
3+
import qualified Data.HashMap.Strict as Map
4+
5+
type Costs = Map.HashMap String Double
6+
type Parents = Map.HashMap String String
7+
type WeightedEdge = (String, Double)
8+
9+
inf = read "Infinity" :: Double
10+
11+
graph = Map.fromList [
12+
("book", [("rarelp", 5.0), ("poster", 0.0)]),
13+
("rarelp", [("guitar", 15.0), ("drumset", 20.0)]),
14+
("poster", [("drumset", 35.0), ("guitar", 30.0)]),
15+
("drumset", [("piano", 10.0)]),
16+
("guitar", [("piano", 20.0)]),
17+
("piano", [])
18+
]
19+
20+
neighbors :: String -> Costs
21+
neighbors node = Map.fromList (maybe [] id (Map.lookup node graph))
22+
23+
closest :: String -> WeightedEdge
24+
closest node = head $ sortBy (\x y -> compare (snd x) (snd y)) $ Map.toList $ (neighbors node)
25+
26+
buildmap graph def initmapfn node = foldl
27+
(\accMap key -> Map.insert key def accMap)
28+
startingMap
29+
keystoadd
30+
where startingMap = initmapfn node
31+
startKeys = node : (Map.keys startingMap)
32+
allKeys = Map.keys graph
33+
keystoadd = filter (not . (`elem` startKeys)) allKeys
34+
35+
initcosts node = buildmap graph inf neighbors node
36+
37+
initparents node = buildmap graph "" ((Map.map (\x -> node)) . neighbors) node
38+
39+
safeHead [] = Nothing
40+
safeHead (x:xs) = Just x
41+
42+
cheapest :: [String] -> Costs -> Maybe WeightedEdge
43+
cheapest processed costs = safeHead $
44+
sortBy (\x y -> compare (snd x) (snd y)) $
45+
filter (\(a, b) -> (not . (`elem` processed)) a) $
46+
Map.toList $
47+
costs
48+
49+
updatecosts :: Costs -> WeightedEdge -> Costs
50+
updatecosts costs (node, cost) = foldl
51+
(\acc (neighbor, neighborcost) ->
52+
let (Just newcost) = min (neighborcost + cost) <$> (Map.lookup neighbor acc)
53+
in Map.insert neighbor newcost acc)
54+
costs
55+
edges
56+
where edges = Map.toList $ neighbors node
57+
58+
updateparents :: Parents -> Costs -> WeightedEdge -> Parents
59+
updateparents parents costs (node, cost) = foldl
60+
(\acc (neighbor, neighborcost) -> case (((cost + neighborcost) <) <$> (Map.lookup neighbor costs)) of
61+
Just True -> Map.insert neighbor node acc
62+
_ -> acc)
63+
parents
64+
edges
65+
where edges = Map.toList $ neighbors node
66+
67+
shortestpath :: Costs -> Parents -> [String] -> (Costs, Parents)
68+
shortestpath costs parents processed = case (cheapest processed costs) of
69+
Just (node, cost) -> shortestpath newcosts newparents (node : processed)
70+
where newcosts = updatecosts costs (node, cost)
71+
newparents = updateparents parents costs (node, cost)
72+
Nothing -> (costs, parents)
73+
74+
costto :: String -> Costs -> Double
75+
costto node costMap = case (Map.lookup node costMap) of
76+
Just cost -> cost
77+
_ -> inf
78+
79+
pathto :: String -> Parents -> [String]
80+
pathto node parentsMap = buildpath node parentsMap [node]
81+
where buildpath node parentsMap acc = case (Map.lookup node parentsMap) of
82+
Just "book" -> "book" : acc
83+
Just parent -> buildpath parent parentsMap (parent : acc)
84+
85+
costs = initcosts "book"
86+
87+
parents = initparents "book"
88+
89+
processed = ["book"]
90+
91+
main = do
92+
(putStrLn . show . (costto "piano")) costsolution
93+
(putStrLn . show . (pathto "piano")) parentsolution
94+
where (costsolution, parentsolution) = shortestpath costs parents processed
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import Control.Applicative
2+
import Data.List
3+
import qualified Data.Set as Set
4+
import qualified Data.HashMap.Strict as Map
5+
6+
stationsMap = Map.fromList [
7+
("kone", Set.fromList(["id", "nv", "ut"])),
8+
("ktwo", Set.fromList(["wa", "id", "mt"])),
9+
("kthree", Set.fromList(["or", "nv", "ca"])),
10+
("kfour", Set.fromList(["nv", "ut"])),
11+
("kfive", Set.fromList(["ca", "az"]))
12+
]
13+
14+
statesNeeded = Set.fromList ["mt", "wa", "or", "id", "nv", "ut", "ca", "az"]
15+
16+
powerSet xs = foldl (\acc x -> acc ++ (map (\e -> x:e) acc)) [[]] xs
17+
18+
allStationCombinations = powerSet $ Map.keys stationsMap
19+
20+
coverage stationsMap stations = map (`Map.lookup` stationsMap) stations
21+
22+
stationsCoverage stations =
23+
fmap (Set.size . (Set.intersection statesNeeded)) $
24+
Just (foldl Set.union Set.empty ) <*>
25+
(sequence (coverage stationsMap stations))
26+
27+
solution = foldl
28+
(\x y -> if stationsCoverage x >= stationsCoverage y then x else y)
29+
first
30+
rest
31+
where (first: rest) =
32+
sortBy (\a b -> compare (length a) (length b)) $
33+
(filter (not . null) allStationCombinations)
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import qualified Data.Set as Set
2+
import qualified Data.HashMap.Strict as Map
3+
4+
stations = Map.fromList [
5+
("kone", Set.fromList(["id", "nv", "ut"])),
6+
("ktwo", Set.fromList(["wa", "id", "mt"])),
7+
("kthree", Set.fromList(["or", "nv", "ca"])),
8+
("kfour", Set.fromList(["nv", "ut"])),
9+
("kfive", Set.fromList(["ca", "az"]))
10+
]
11+
12+
statesNeeded = Set.fromList ["mt", "wa", "or", "id", "nv", "ut", "ca", "az"]
13+
14+
bestStation statesNeeded selectedStations stations = foldl
15+
(\a@(station1, states1) b@(station2, states2) ->
16+
let fn states = Set.size $ (Set.intersection statesNeeded states)
17+
coverage1 = fn states1
18+
coverage2 = fn states2
19+
in if coverage1 > coverage2 then a else b
20+
)
21+
x
22+
xs
23+
where (x: xs) = filter (\(station, states) -> not $ station `elem` selectedStations) $ Map.toList stations
24+
25+
26+
stationSet statesNeeded finalStations =
27+
let (station, coveredStations) = bestStation statesNeeded finalStations stations
28+
neededStations = Set.difference statesNeeded coveredStations
29+
newStations = station : finalStations
30+
in if (Set.size statesNeeded > 0) then stationSet neededStations newStations else finalStations
31+
32+
finalSet = stationSet statesNeeded []
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import Control.Applicative
2+
import Data.List
3+
import qualified Data.Set as Set
4+
import qualified Data.HashMap.Strict as Map
5+
6+
items = Map.fromList [
7+
("stereo", (4, 3000)),
8+
("laptop", (3, 2000)),
9+
("guitar", (1, 1500))
10+
]
11+
12+
value set = (a, b)
13+
where
14+
weightandvalues = (sequence $ map (`Map.lookup` items) set)
15+
Just (a,b) = Just (foldl (\(a,b) (c,d) -> (a+c, b+d)) (0,0)) <*> weightandvalues
16+
17+
powerSet xs = foldl (\acc x -> acc ++ (map (\e -> x:e) acc)) [[]] xs
18+
19+
solution = foldl
20+
(\acc v -> let
21+
(firstweight, firstvalue) = value acc
22+
(secondweight, secondvalue) = value v
23+
in if firstweight <= 4 && firstvalue >= secondvalue then acc else if secondweight <= 4 then v else acc)
24+
first
25+
rest
26+
where
27+
(first: rest) = filter (not . null) $ powerSet $ (Map.keys items)
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import qualified Data.HashMap.Strict as Map
2+
import Data.Array
3+
4+
type Grid = Array (Integer, Integer) (Integer, [Char])
5+
6+
itemsMap = Map.fromList [
7+
("stereo", (4, 3000)),
8+
("laptop", (3, 2000)),
9+
("guitar", (1, 1500)),
10+
("iphone", (1, 2000))
11+
]
12+
13+
weightOf item = case Map.lookup item itemsMap of
14+
Just (w, v) -> w
15+
otherwise -> 0
16+
17+
valueOf item = case Map.lookup item itemsMap of
18+
Just (w, v) -> v
19+
otherwise -> 0
20+
21+
emptyGrid :: Grid
22+
emptyGrid = array ((0,0), (3,4)) [((x,y), (0, "")) | x <- [0..3], y <- [0..4]]
23+
24+
best :: Grid -> Integer -> Integer -> String -> (Integer, String)
25+
best arr row col item =
26+
let weight = weightOf item
27+
value = valueOf item
28+
(previousMax, previousItems) = if (row /= 0) then arr ! (row - 1, col) else (0, "")
29+
(valueOfRemainingSpace, itemsInRemainingSpace) =
30+
if (row /= 0 && (col - weight) >= 0)
31+
then arr ! (row - 1, col - weight)
32+
else (0, "")
33+
in if (previousMax > (value + valueOfRemainingSpace))
34+
then arr ! (row - 1, col)
35+
else (value + valueOfRemainingSpace, itemsInRemainingSpace ++ " " ++ item)
36+
37+
fillPrevBest arr row col =
38+
if row /= 0 then (//) arr [((row, col), arr ! (row - 1, col))] else arr
39+
40+
fillGrid emptyGrid = foldl
41+
(\acc pair ->
42+
let row = fst pair
43+
item = snd pair
44+
(weight, value) = (weightOf item, valueOf item)
45+
in foldl
46+
(\arr col ->
47+
case weight <= col of
48+
True -> (//) arr [((row, col), best arr row col item)]
49+
False -> fillPrevBest arr row col
50+
)
51+
acc
52+
[0..4]
53+
)
54+
emptyGrid
55+
items
56+
where items = zip [0..3] $ Map.keys itemsMap
57+
58+
solution = foldl
59+
(\(x, a) (y, b) -> if x > y then (x, a) else (y, b))
60+
first
61+
rest
62+
where (first: rest) = elems $ fillGrid emptyGrid

0 commit comments

Comments
 (0)