import Aoc import Data.Char ( ord, chr ) import Data.List ( group, nub ) import Data.Bifunctor ( bimap ) toBase26' :: Char -> Int toBase26' = (\n->n-97) . ord fromBase26' :: Int -> Char fromBase26' = chr . (97+) toBase26 :: [Char] -> [Int] toBase26 = reverse . map toBase26' fromBase26 :: [Int] -> [Char] fromBase26 = reverse . map fromBase26' next :: [Int] -> [Int] next (25:rest) = 0:next rest next (x:rest) | x `elem` [7,10,13] = x+2:rest -- skip i,o,l | otherwise = x+1:rest lengthy :: [a] -> Bool lengthy = (>1) . length getAnswer :: [[Int]] -> [Char] getAnswer = fromBase26 . head part1 :: String -> (String, [[Int]]) part1 = (\ps -> (getAnswer ps, tail ps)) . filter isSecure . iterate next . toBase26 where hasStraight = any lengthy . filter ((==1) . head) . group . map (uncurry (-)) . adjacents hasNoIOL = not . any (`elem` [8,14,11]) hasPair = lengthy . nub . map head . filter lengthy . group isSecure ns = hasStraight ns && hasNoIOL ns && hasPair ns part2 :: p -> [[Int]] -> String part2 _ = getAnswer main :: IO () main = aocMain' single part1 part2