1
0
Fork 0
projecteuler/83_alt.hs

72 lines
2.4 KiB
Haskell
Raw Normal View History

import Data.List.Split
import Data.Matrix
import Data.Maybe
import Data.Foldable
import Data.PQueue.Min
type Value = Integer
2017-10-24 05:47:05 +00:00
type Distance = Integer
type Position = (Int, Int)
data Element = Element {
value :: Value,
2017-10-24 05:47:05 +00:00
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
2017-10-24 05:47:05 +00:00
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
2017-10-24 05:47:05 +00:00
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)
2017-10-24 05:47:05 +00:00
initialMinQ = singleton $ PQE initialElement $ value initialElement
lastPos = (nrows m, ncols m)
2017-10-24 05:47:05 +00:00
in dijkstra lastPos m initialMinQ
setInitial :: Matrix Element -> Matrix Element
setInitial m =
let v = value $ m ! (1, 1)
2017-10-24 05:47:05 +00:00
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