45 lines
1.4 KiB
Haskell
45 lines
1.4 KiB
Haskell
module Main where
|
|
|
|
import System.Environment (getArgs)
|
|
import Data.Maybe (mapMaybe)
|
|
|
|
import Text.Parsec (parse, Parsec, endBy, sepBy1, char, newline, many)
|
|
import Text.ParserCombinators.Parsec.Number (decimal)
|
|
|
|
type PageOrdering = (Int, Int)
|
|
type PagesUpdate = [Int]
|
|
|
|
printInfo :: Parsec String () ([PageOrdering], [PagesUpdate])
|
|
printInfo = (,) <$> orderings <*> (newline *> pagesUpdates) <* many (char '\n')
|
|
where
|
|
pagesUpdates :: Parsec String () [PagesUpdate]
|
|
pagesUpdates = endBy (sepBy1 decimal $ char ',') newline
|
|
|
|
orderings :: Parsec String () [PageOrdering]
|
|
orderings = endBy ((,) <$> decimal <*> (char '|' *> decimal)) $ char '\n'
|
|
|
|
allDependencies :: [a] -> [(a, a)]
|
|
allDependencies (h:tl) = map (flip (,) h) tl ++ allDependencies tl
|
|
allDependencies [] = []
|
|
|
|
middleElement :: [a] -> Maybe a
|
|
middleElement [] = Nothing
|
|
middleElement [a] = Just a
|
|
middleElement (_:h':tl) = case reverse (h':tl) of
|
|
(_:middle) -> middleElement middle
|
|
[] -> Nothing
|
|
|
|
part1 :: FilePath -> IO Int
|
|
part1 fp = do
|
|
content <- readFile fp
|
|
(requiredOrderings, pagesUpdates) <- either (fail . show) return $ parse printInfo fp content
|
|
let wellOrdered = filter (all (`notElem` requiredOrderings) . allDependencies) pagesUpdates
|
|
return $ sum $ mapMaybe middleElement wellOrdered
|
|
|
|
main :: IO ()
|
|
main = do
|
|
args <- getArgs
|
|
(fp:_) <- return args
|
|
resPart1 <- part1 fp
|
|
putStrLn $ "Solution (Part 1) : " ++ show resPart1
|