44 lines
1.1 KiB
Haskell
44 lines
1.1 KiB
Haskell
{-# OPTIONS_GHC -Wno-x-partial #-}
|
|
|
|
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 |