Compare commits
	
		
			No commits in common. "a31509d093b1e2bab4d4d17eca729c22d49bfce4" and "c7f29e21549c0f2dcf30c9f2d0834ed1a787752b" have entirely different histories.
		
	
	
		
			a31509d093
			...
			c7f29e2154
		
	
		
					 4 changed files with 0 additions and 143 deletions
				
			
		|  | @ -1,75 +0,0 @@ | ||||||
| module LeastReachableCity(dijkstra, leastReachableCity) where |  | ||||||
| 
 |  | ||||||
| import Types  |  | ||||||
| import qualified Data.Map as Map |  | ||||||
| import qualified Data.Set as Set |  | ||||||
| 
 |  | ||||||
| -- Well, it's just a magic number, because it's too much hassle to implement type like "Len val | Infinity"  |  | ||||||
| -- TODO: get graph radius and use this number as infinity |  | ||||||
| infinity :: Len |  | ||||||
| infinity = 999999 :: Len |  | ||||||
| 
 |  | ||||||
| leastReachableCity :: Graph -> Len -> (Point, Int) |  | ||||||
| leastReachableCity graph mileage = foldl (\(p, n) (p', n') ->  |  | ||||||
|         if n' < n then (p',n')  |  | ||||||
|         else (p, n))  |  | ||||||
|     (-1, infinity) [(city, countReachableCities $ dijkstra city graph) | city <- Set.toList $ fst $ countVertices graph] where |  | ||||||
|         countReachableCities :: Distances -> Int |  | ||||||
|         countReachableCities distances = Map.foldl (\n val -> if (val <= mileage) && (val /= 0) then n + 1 else n) 0 distances  |  | ||||||
| 
 |  | ||||||
| dijkstra :: Point -> Graph -> Distances |  | ||||||
| dijkstra start graph = dijkstra' start graph visited_init to_visit_init distances_init where |  | ||||||
|     -- Helper (so we don' need to call dijkstra initializing empty visited, to_visit etc) |  | ||||||
|     dijkstra' :: Point -> Graph -> Vertices -> Vertices -> Distances -> Distances  |  | ||||||
|     dijkstra' start graph visited to_visit distances = if Set.null to_visit  |  | ||||||
|         then  |  | ||||||
|             distances |  | ||||||
|         else |  | ||||||
|             dijkstra'  |  | ||||||
|                 (findMinNotVisited to_visit distances)  |  | ||||||
|                 graph  |  | ||||||
|                 (Set.insert start visited)  |  | ||||||
|                 (Set.union (Set.delete start to_visit) $ findNotVisitedNeighbours graph visited start)  |  | ||||||
|                 (updateDistances graph start distances) |  | ||||||
|     -- Other |  | ||||||
|     to_visit_init = (Set.insert start $ Set.empty :: Vertices) |  | ||||||
|     distances_init = (infinityDistances start $ snd $ countVertices graph) |  | ||||||
|     visited_init = (Set.empty :: Vertices)  |  | ||||||
| 
 |  | ||||||
| updateDistances :: Graph -> Point -> Distances -> Distances |  | ||||||
| updateDistances graph point distances = snd $ Map.foldrWithKey decideMin ((point, Map.findWithDefault (-1) point distances), Map.empty :: Distances) distances where |  | ||||||
|     decideMin ::  Point -> Len -> ((Point, Len), Distances) -> ((Point, Len), Distances) |  | ||||||
|     decideMin p' l' ((p, l), dist) = if findDistance graph p p' + l < l' then  |  | ||||||
|         ((p, l), Map.insert p' (l + findDistance graph p p') dist) else |  | ||||||
|         ((p, l), Map.insert p' l' dist) |  | ||||||
| 
 |  | ||||||
| findDistance :: Graph -> Point -> Point -> Len |  | ||||||
| findDistance ((Node (a, b, len)) : graph) p p' = if ((a == p) && (b == p') || (b == p) && (a == p')) then len else findDistance graph p p'   |  | ||||||
| findDistance _ _ _ = infinity |  | ||||||
| 
 |  | ||||||
| findMinNotVisited :: Vertices -> Distances -> Point   |  | ||||||
| findMinNotVisited to_visit distances = fst $ Set.foldl (\(p, l) p' -> case Map.lookup p' distances of  |  | ||||||
|     (Just l') -> if l' < l then  |  | ||||||
|             (p', l')  |  | ||||||
|         else (p,l))  |  | ||||||
|     (-1, infinity) to_visit  |  | ||||||
| 
 |  | ||||||
| infinityDistances :: Point -> Int -> Distances |  | ||||||
| infinityDistances point n = Map.fromList $ (point, 0) : [(x, infinity) | x <- [1..n], x /= point]  |  | ||||||
| 
 |  | ||||||
| countVertices :: Graph -> (Vertices, Int) |  | ||||||
| countVertices graph = foldl f (Set.empty :: Vertices, 0) graph where |  | ||||||
|     f :: (Vertices, Int) -> Node -> (Vertices, Int) |  | ||||||
|     f (vertices, n) (Node (a, b, _)) =  |  | ||||||
|         let aIsNotMember = not $ Set.member a vertices  |  | ||||||
|             bIsNotMember = not $ Set.member b vertices in if (aIsNotMember && bIsNotMember) then (Set.insert a $ Set.insert b vertices, n + 2)  |  | ||||||
|                 else if (aIsNotMember) then (Set.insert a vertices, n + 1)  |  | ||||||
|                     else if (bIsNotMember) then (Set.insert b vertices, n + 1)  |  | ||||||
|                         else (vertices, n) |  | ||||||
| 
 |  | ||||||
| findNotVisitedNeighbours :: Graph -> Vertices -> Point -> Vertices  |  | ||||||
| findNotVisitedNeighbours graph visited point = foldl f (Set.empty :: Vertices) graph where |  | ||||||
|     f :: Vertices -> Node -> Vertices  |  | ||||||
|     f vertices (Node (a, b, _)) = if ((a == point) && (not $ Set.member b visited)) then Set.insert b vertices  |  | ||||||
|         else if ((b == point) && (not $ Set.member a visited)) then Set.insert a vertices |  | ||||||
|             else vertices |  | ||||||
|  | @ -1,13 +0,0 @@ | ||||||
| module Types where |  | ||||||
| 
 |  | ||||||
| import qualified Data.Map as Map |  | ||||||
| import qualified Data.Set as Set |  | ||||||
| 
 |  | ||||||
| type Point = Int |  | ||||||
| type Len = Int |  | ||||||
|      |  | ||||||
| data Node = Node (Point, Point, Len) deriving Show |  | ||||||
| type Graph = [Node] |  | ||||||
| 
 |  | ||||||
| type Distances = Map.Map Point Len |  | ||||||
| type Vertices = Set.Set Point |  | ||||||
|  | @ -1,9 +0,0 @@ | ||||||
| 4 |  | ||||||
| 
 |  | ||||||
| 1 2 10 |  | ||||||
| 1 4 2 |  | ||||||
| 1 3 3 |  | ||||||
| 3 2 5 |  | ||||||
| 2 4 6 |  | ||||||
| 4 5 4 |  | ||||||
| 5 3 1 |  | ||||||
|  | @ -1,46 +0,0 @@ | ||||||
| module Main where |  | ||||||
| 
 |  | ||||||
| import System.IO  |  | ||||||
| import System.Environment |  | ||||||
| 
 |  | ||||||
| import qualified Data.Map as Map |  | ||||||
| import qualified Data.Set as Set |  | ||||||
| 
 |  | ||||||
| import LeastReachableCity |  | ||||||
| import Types |  | ||||||
| 
 |  | ||||||
| {- format of input file is: |  | ||||||
|  - mileage |  | ||||||
|  - from to len |  | ||||||
|  - from to len |  | ||||||
|  - ... |  | ||||||
|  - where "from" and "to" are numbers of graph vertices, "len" is distance between them |  | ||||||
|  - -} |  | ||||||
| main :: IO() |  | ||||||
| main = do |  | ||||||
|     argv <- getArgs |  | ||||||
| 
 |  | ||||||
|     filename <- if not $ null argv then do |  | ||||||
|         head <$> getArgs |  | ||||||
|     else do |  | ||||||
|         putStrLn "Usage: ./lrc [filename]\nNow defaulting to file \"data\"" |  | ||||||
|         return "data" |  | ||||||
| 
 |  | ||||||
|     content <- readFile filename |  | ||||||
|     let mileage = read $ head $ lines content :: Len |  | ||||||
|     let graph = readGraph $ tail content |  | ||||||
|     let (city, n) = leastReachableCity graph mileage |  | ||||||
|     putStrLn $ "The least reachable city is " ++ (show city) ++ " (" ++ (show n) ++ " city/ies is/are reachable)" |  | ||||||
| 
 |  | ||||||
| {- For parsing graph using content of the file -}  |  | ||||||
| parseStrNode :: [String] -> Node |  | ||||||
| parseStrNode [a, b, c] = Node (p a, p b, l c) where |  | ||||||
|     p x = read x :: Point |  | ||||||
|     l x = read x :: Len |  | ||||||
| 
 |  | ||||||
| readGraph :: String -> Graph |  | ||||||
| readGraph content = parse lst where |  | ||||||
|             parse (x:xs) = if length ws == 3 then (parseStrNode ws) : (parse xs) else parse xs where |  | ||||||
|                 ws = words x |  | ||||||
|             parse _ = []  |  | ||||||
|             lst = lines content |  | ||||||
		Reference in a new issue