module Main where import Data.Char import Numeric pairs :: String -> [(Char,Char)] pairs (a:b:cs) = (a,b) : pairs (b:cs) pairs _ = [] allEqual :: (Eq a) => [a] -> Bool allEqual (a:b:cs) = if a /= b then False else allEqual (b:cs) allEqual _ = True hasStraight :: String -> Bool hasStraight (a:b:c:ds) = (y == x + 1 && z == x + 2) || hasStraight (b:c:ds) where (x,y,z) = (ord a,ord b,ord c) hasStraight _ = False hasForbidden :: String -> Bool hasForbidden [] = False hasForbidden (x:xs) = x /= 'i' && x /= 'o' && x /= 'l' && not (hasForbidden xs) hasTwoPairs :: String -> Bool hasTwoPairs s = (not.allEqual) $ filter (\(a,b) -> a == b) (pairs s) isValid :: String -> Bool isValid s = hasStraight s && not (hasForbidden s) && hasTwoPairs s show26 :: Int -> String show26 n = showIntAtBase 26 (\d -> chr (97 + d)) n "" read26 :: String -> Int read26 = fst . head . readInt 26 (\c -> let o = ord c in 97 <= o && o <= 122) (\c -> ord c - 97) pad :: Int -> Char -> String -> String pad n c s = if length s < n then pad n c (c:s) else s nextpass :: String -> String nextpass s = pad (length s) 'a' $ show26 $ succ $ read26 s nextvalidpass :: String -> String nextvalidpass = head . dropWhile (not . isValid) . iterate nextpass day11 :: IO () day11 = do print $ nextvalidpass $ nextpass $ nextvalidpass "cqjxjnds" main = day11