60 lines
2.1 KiB
Haskell
60 lines
2.1 KiB
Haskell
|
import Data.List.Split
|
||
|
import Data.Matrix
|
||
|
import Data.Maybe
|
||
|
|
||
|
type Value = Integer
|
||
|
data IsVisited = Visited | Unvisited deriving (Eq, Show)
|
||
|
type Position = (Int, Int)
|
||
|
data Element = Element Value IsVisited Position deriving (Eq, Show)
|
||
|
|
||
|
getUnvisitedNeighbours :: Matrix Element -> Element -> [Element]
|
||
|
getUnvisitedNeighbours m (Element _ _ (i, j)) =
|
||
|
filter (\(Element _ isVisited _) -> isVisited == Visited)
|
||
|
(catMaybes [safeGet (i - 1) j m
|
||
|
,safeGet (i + 1) j m
|
||
|
,safeGet i (j - 1) m
|
||
|
,safeGet i (j + 1) m])
|
||
|
|
||
|
getNeighbourDistances :: Element -> [Element] -> [Element]
|
||
|
getNeighbourDistances e = map (addValue e)
|
||
|
where addValue (Element ve isVisited _) (Element vn _ p) = Element (ve + vn) isVisited p
|
||
|
|
||
|
getMin :: Value -> Value -> Value
|
||
|
getMin v1 0 = v1
|
||
|
getMin 0 v2 = v2
|
||
|
getMin v1 v2 = min v1 v2
|
||
|
|
||
|
dijkstraMatrix :: Matrix Element -> (Value, Position)
|
||
|
dijkstraMatrix m =
|
||
|
let neighbourDistanceMatrix = fmap (\e -> getNeighbourDistances e (getUnvisitedNeighbours m e)) m
|
||
|
-- fold over Visited with getMin
|
||
|
in (0, (0, 0))
|
||
|
-- for unvisited element in matrix
|
||
|
-- for unvisited neighbour of element
|
||
|
-- if element value + neighbour value < min then set as min
|
||
|
-- return min; default is (0, (0, 0))
|
||
|
|
||
|
nextMatrix :: Matrix Element -> Matrix Element
|
||
|
nextMatrix m =
|
||
|
let (minValue, position) = dijkstraMatrix m
|
||
|
maybeMatrix = safeSet (Element minValue Visited position) position m
|
||
|
in case maybeMatrix of
|
||
|
Just next -> next
|
||
|
Nothing -> m
|
||
|
|
||
|
initElement :: Matrix Integer -> Position -> Element
|
||
|
initElement m p =
|
||
|
let value = m ! p
|
||
|
in Element value Unvisited p
|
||
|
|
||
|
toElementMatrix :: Matrix Integer -> Matrix Element
|
||
|
toElementMatrix m =
|
||
|
matrix (nrows m) (ncols m) (initElement m)
|
||
|
|
||
|
main :: IO ()
|
||
|
main = do
|
||
|
contents <- readFile "p081_matrix.txt"
|
||
|
let listsMatrix = map (map read . (splitOn ",")) $ lines contents :: [[Integer]]
|
||
|
valueMatrix = fromLists listsMatrix
|
||
|
mtrx = toElementMatrix valueMatrix
|
||
|
print mtrx
|