noBadStrings input = all (not . flip isInfixOf input) badstrings
  where badstrings = ["ab", "cd", "pq", "xy"]

hasPalindromeTriplet :: String -> Bool
hasPalindromeTriplet = any isPalindrome . triplets
  where isPalindrome = (==) <*> reverse
        triplets input = take (length input - 3 + 1) $ map (take 3) $ tails input

repeatedPair :: String -> Bool
repeatedPair = any repeatedPrefixPair . takeWhile ((>=4) . length) . tails
  where repeatedPrefixPair input = take 2 input `isInfixOf` drop 2 input

applyRules :: [String -> Bool] -> String -> Bool
applyRules rules string = and $ sequence rules string