Created
December 5, 2015 18:06
-
-
Save travisby/2c99b6065e0454b12825 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main where | |
import Data.List | |
import Debug.Trace | |
main = do | |
input <- getContents | |
let xs = lines input | |
putStr "Old rules: " | |
print (length (filter (allPredicates [atLeastNVowels 3, repeats, not . containsBlacklistedPhrase]) xs)) | |
putStr "New rules: " | |
print (length (filter (allPredicates [hasNonContiguousPairs, hasSandwich]) xs)) | |
atLeastNVowels :: Int -> String -> Bool | |
atLeastNVowels 0 _ = True | |
atLeastNVowels _ [] = False | |
atLeastNVowels n (x:xs) | |
| isVowel x = atLeastNVowels (n - 1) xs | |
| otherwise = atLeastNVowels n xs | |
isVowel :: Char -> Bool | |
isVowel 'a' = True | |
isVowel 'e' = True | |
isVowel 'i' = True | |
isVowel 'o' = True | |
isVowel 'u' = True | |
isVowel _ = False | |
repeats :: String -> Bool | |
repeats [] = False | |
repeats (x:[]) = False | |
repeats (x:y:xs) = x == y || repeats (y:xs) | |
containsBlacklistedPhrase :: String -> Bool | |
containsBlacklistedPhrase [] = False | |
containsBlacklistedPhrase (x:[]) = False | |
containsBlacklistedPhrase (x:y:xs) | |
| [x,y] == "ab" = True | |
| [x,y] == "cd" = True | |
| [x,y] == "pq" = True | |
| [x,y] == "xy" = True | |
| otherwise = containsBlacklistedPhrase (y:xs) | |
notContainsBlacklistedPhrase :: String -> Bool | |
notContainsBlacklistedPhrase = not . containsBlacklistedPhrase | |
-- terribly inefficient. O(n^2) | |
-- we had a problem ignoring pairs like "aaa" where there is ["aa", "aa"] in the list | |
-- in the future we could do a UNIX-like uniq on the list (to remove all next-to-eachother matches) | |
-- and then do our comparison without any of the splitAt nonsense... however it'd still be O(n^2) | |
-- the faster (and probably more right) solution would be to combine every pair into a map[string]int | |
hasNonContiguousPairs :: String -> Bool | |
hasNonContiguousPairs str = any (\pair -> pair `elem` snd (splitAt (head (elemIndices pair allPairs) + 2) allPairs)) allPairs | |
where allPairs = hasNonContigiousPairsHelper str | |
hasNonContigiousPairsHelper :: String -> [String] | |
hasNonContigiousPairsHelper [] = [] | |
hasNonContigiousPairsHelper (x:[]) = [[x]] | |
hasNonContigiousPairsHelper (x:y:[]) = [[x, y]] | |
hasNonContigiousPairsHelper (x:y:xs) = [x,y]:hasNonContigiousPairsHelper (y:xs) | |
hasSandwich :: String -> Bool | |
hasSandwich [] = False | |
hasSandwich (_:[]) = False | |
hasSandwich (_:_:[]) = False | |
hasSandwich (a:b:c:xs) = a == c && a /= b || hasSandwich (b:c:xs) | |
allPredicates :: [a -> Bool] -> a -> Bool | |
allPredicates funcs a = all (\f -> f a) funcs |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment