import Data.List.Split import Data.List import Data.Maybe getRightMin :: [Integer] -> [Integer] -> Maybe Integer getRightMin prevRight currRight = case currRight of [] -> Nothing _ -> Just $ minimum $ zipWith (+) prevRight $ tail $ scanl (+) 0 currRight getLeftMin :: [Integer] -> [Integer] -> Maybe Integer getLeftMin prevLeft currLeft = getRightMin (reverse prevLeft) (reverse currLeft) type Acc = ([Integer], [Integer], [Integer], [Integer]) type PrevCurr = (Integer, Integer) getMin :: Acc -> PrevCurr -> Integer getMin (prevLeft, currLeft, prevRight, currRight) (prev, curr) = curr + (minimum $ catMaybes [getLeftMin prevLeft currLeft, Just prev, getRightMin prevRight currRight]) shift :: Acc -> PrevCurr -> Acc shift (prevLeft, currLeft, prevRight, currRight) (prev, curr) = (prevLeft ++ [prev], currLeft ++ [curr], tail prevRight, tail currRight) getNextLine :: [Integer] -> [Integer] -> [Integer] getNextLine prevLine currLine = let initPrevLeft = [] initCurrLeft = [] initPrevRight = tail prevLine initCurrRight = tail currLine next acc prevCurr = (shift acc prevCurr, getMin acc prevCurr) in snd $ mapAccumL next (initPrevLeft, initCurrLeft, initPrevRight, initCurrRight) $ zip prevLine currLine main :: IO () main = do contents <- readFile "p081_matrix.txt" let fileLines = lines contents upDownMatrix = map (map read . (splitOn ",")) fileLines matrix = transpose upDownMatrix print $ minimum $ foldl getNextLine (head matrix) (tail matrix)