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