Skip to content

Instantly share code, notes, and snippets.

@travisby
Created December 5, 2015 18:06
Show Gist options
  • Save travisby/2c99b6065e0454b12825 to your computer and use it in GitHub Desktop.
Save travisby/2c99b6065e0454b12825 to your computer and use it in GitHub Desktop.
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