never executed always true always false
    1 {-|
    2 Module:      Y2015.D11
    3 Description: Advent of Code Day 11 Solutions.
    4 License:     MIT
    5 Maintainer:  @tylerjl
    6 
    7 Solutions to the day 11 set of problems for <adventofcode.com>.
    8 -}
    9 module Y2015.D11
   10   ( rotate
   11   ) where
   12 
   13 import Data.List (group, isInfixOf, tails)
   14 
   15 import Y2015.Util ((<&&>))
   16 
   17 alphabet :: String
   18 alphabet = ['a' .. 'z']
   19 
   20 meetsReqs :: String -> Bool
   21 meetsReqs = hasPairs <&&> (not . forbidden) <&&> hasStraightFast
   22 
   23 hasPairs :: String -> Bool
   24 hasPairs = (1 <) . length . filter ((<) 1 . length) . group
   25 
   26 forbidden :: String -> Bool
   27 forbidden = any (`elem` ("iol" :: String))
   28 
   29 hasStraightFast :: String -> Bool
   30 hasStraightFast = not . null . filterAsc . subSeqs
   31   where
   32     filterAsc = filter (`isInfixOf` alphabet)
   33     subSeqs = takeWhile ((== 3) . length) . map (take 3) . tails
   34 
   35 increment :: String -> String
   36 increment = reverse . step . reverse
   37   where
   38     step [] = []
   39     step [x]
   40       | x == 'z' = "aa"
   41       | otherwise = [succ x]
   42     step (x:xs)
   43       | x /= 'z' = succ x : xs
   44       | otherwise = 'a' : step xs
   45 
   46 -- |Rotate a password within specific rules
   47 rotate
   48   :: String -- ^ Starting password
   49   -> String -- ^ Next valid password
   50 rotate = nextValid . increment
   51   where
   52     nextValid = head . filter meetsReqs . iterate increment