module AoC
    ( (.:)
    , enumerate
    , oneCompleteResult
    , splitOnEmptyLines
    , runAoC
    )
where

import Data.Function (on)
import Data.List (groupBy)
import Text.ParserCombinators.ReadP

(.:) :: (c -> d) -> (a -> b -> c) -> a -> b -> d
f .: g = (f .) . g
infixl 8 .:

enumerate :: Enum i => i -> [a] -> [(i, a)]
enumerate _ [] = []
enumerate i (x:xs) = (i, x) : enumerate (succ i) xs

oneCompleteResult :: ReadP a -> String -> Maybe a
oneCompleteResult p s = case readP_to_S (p <* eof) s of
                          [(x, "")] -> Just x
                          _ -> Nothing

splitOnEmptyLines :: String -> [[String]]
splitOnEmptyLines = filter (not . any null) . groupBy ((==) `on` null) . lines

runAoC :: (Show r1, Show r2) => (String -> i) -> (i -> r1) -> (i -> r2) -> IO ()
runAoC inputTransform part1 part2 = do
    contents <- inputTransform <$> getContents
    print $ part1 contents
    print $ part2 contents
