72 lines
2.4 KiB
Haskell
72 lines
2.4 KiB
Haskell
import Data.List.Split
|
|
import Data.Matrix
|
|
import Data.Maybe
|
|
import Data.Foldable
|
|
import Data.PQueue.Min
|
|
|
|
type Value = Integer
|
|
type Distance = Integer
|
|
type Position = (Int, Int)
|
|
data Element = Element {
|
|
value :: Value,
|
|
distance :: Maybe Distance, -- Nothing represents infinity
|
|
position :: Position
|
|
} deriving (Eq, Show)
|
|
data PQE = PQE Element Distance deriving (Eq, Show)
|
|
|
|
instance Ord PQE where
|
|
PQE _ Nothing <= _ = False
|
|
_ <= PQE _ Nothing = True
|
|
PQE _ (Just d1) <= PQE _ (Just d2) = d1 <= d2
|
|
|
|
getNeighbours :: Matrix Element -> Element -> [Element]
|
|
getNeighbours m e =
|
|
let (i, j) = position e
|
|
in catMaybes [safeGet (i - 1) j m,
|
|
safeGet (i + 1) j m,
|
|
safeGet i (j - 1) m,
|
|
safeGet i (j + 1) m]
|
|
|
|
dijkstra :: Position -> Matrix Element -> MinQueue PQE -> Distance
|
|
dijkstra p m q =
|
|
let PQE minElement minDistance = findMin q
|
|
in if position minElement == p
|
|
then minDistance
|
|
else let (newM, newQ) = foldr update (m, q) $ getNeighbours m minElement
|
|
in dijkstra p newM newQ
|
|
where update neighbour (prevM, prevQ) =
|
|
let newDistance = minDistance + value neighbour
|
|
in case distance neighbour of
|
|
Nothing -> undefined
|
|
Just d -> undefined
|
|
|
|
findShortestPathLength :: Matrix Element -> Distance
|
|
findShortestPathLength m =
|
|
let initialElement = m ! (1, 1)
|
|
initialMinQ = singleton $ PQE initialElement $ value initialElement
|
|
lastPos = (nrows m, ncols m)
|
|
in dijkstra lastPos m initialMinQ
|
|
|
|
|
|
setInitial :: Matrix Element -> Matrix Element
|
|
setInitial m =
|
|
let v = value $ m ! (1, 1)
|
|
in unsafeSet (Element v (Just v) (1, 1)) (1, 1) m
|
|
|
|
initElement :: Matrix Integer -> Position -> Element
|
|
initElement m p =
|
|
let value = m ! p
|
|
in Element value Nothing p
|
|
|
|
toElementMatrix :: Matrix Integer -> Matrix Element
|
|
toElementMatrix m =
|
|
matrix (nrows m) (ncols m) (initElement m)
|
|
|
|
main :: IO ()
|
|
main = do
|
|
contents <- readFile "p083_matrix.txt"
|
|
let listsMatrix = fmap (fmap read . (splitOn ",")) $ lines contents :: [[Integer]]
|
|
valueMatrix = fromLists listsMatrix
|
|
unvisitedMatrix = toElementMatrix valueMatrix
|
|
mtrx = setInitial unvisitedMatrix
|
|
print $ findShortestPathLength mtrx |