module Aoc where

aocMain' :: (Show p, Show a) => ([String] -> p) -> (p -> (a, c)) -> (p -> c -> a) -> IO ()
aocMain' parseFile part1 part2 = do
    contents <- readFile "input.txt"
    let input = parseFile $ lines contents
    let (part1Answer, data') = part1 input
    putStrLn $ "Part 1: " ++ show part1Answer
    let part2Answer = part2 input data'
    putStrLn $ "Part 2: " ++ show part2Answer

dup :: a -> (a, a)
dup a = (a, a)

aocMain :: (Show p, Show a) => ([String] -> p) -> (p -> a) -> (p -> a) -> IO ()
aocMain parseFile part1 part2 = aocMain' parseFile ((,()) . part1) (const' part2)

const' :: (a -> b) -> a -> c -> b
const' f a _ = f a

enumerate :: [a] -> [(Int, a)]
enumerate = zip [0..]

unimplemented :: (Show p, Show a) => p -> a
unimplemented = error . show

pair :: [a] -> (a, a)
pair as = let [a1, a2] = as in (a1, a2)

unpair :: (a, a) -> [a]
unpair (a, b) = [a, b]

triplet :: [a] -> (a, a, a)
triplet as = let [a1, a2, a3] = as in (a1, a2, a3)

single :: [a] -> a
single as = let [a] = as in a

both :: (a -> b) -> (a, a) -> (b, b)
both f (a, b) = (f a, f b)

lastSplit :: Int -> [a] -> ([a], [a])
lastSplit n as = splitAt (length as - n) as

remove :: Int -> [a] -> (a, [a])
remove n xs = let (front, a:rest) = splitAt n xs in (a, front ++ rest)

permutations :: [a] -> [[a]]
permutations [] = [[]]
permutations xs = concatMap (\n -> let (a, rest) = remove n xs in map (a:) $ permutations rest) [0..length xs-1]

adjacents :: [a] -> [(a, a)]
adjacents as = zip as $ tail as