{-# Language BlockArguments, LambdaCase #-}
module Main where
import Advent (getInputLines, countBy)
import Data.List (isInfixOf, tails)
main :: IO ()
IO ()
main =
do [String]
strs <- Int -> Int -> IO [String]
getInputLines Int
2015 Int
5
Int -> IO ()
forall a. Show a => a -> IO ()
print ((String -> Bool) -> [String] -> Int
forall (f :: * -> *) a. Foldable f => (a -> Bool) -> f a -> Int
countBy String -> Bool
part1 [String]
strs)
Int -> IO ()
forall a. Show a => a -> IO ()
print ((String -> Bool) -> [String] -> Int
forall (f :: * -> *) a. Foldable f => (a -> Bool) -> f a -> Int
countBy String -> Bool
part2 [String]
strs)
part1 :: String -> Bool
part1 :: String -> Bool
part1 String
str = String -> Bool
threeVowels String
str Bool -> Bool -> Bool
&& String -> Bool
hasDouble String
str Bool -> Bool -> Bool
&& String -> Bool
noProhibited String
str
part2 :: String -> Bool
part2 :: String -> Bool
part2 String
str = String -> Bool
pairTwice String
str Bool -> Bool -> Bool
&& String -> Bool
nearby String
str
threeVowels :: String -> Bool
threeVowels :: String -> Bool
threeVowels = Bool -> Bool
not (Bool -> Bool) -> (String -> Bool) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null (String -> Bool) -> (String -> String) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> String -> String
forall a. Int -> [a] -> [a]
drop Int
2 (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
filter (Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
"aeiou")
hasDouble :: String -> Bool
hasDouble :: String -> Bool
hasDouble =
(String -> Bool) -> String -> Bool
search \case
Char
x:Char
y:String
_ -> Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
y
String
_ -> Bool
False
noProhibited :: String -> Bool
noProhibited :: String -> Bool
noProhibited String
str = Bool -> Bool
not ((String -> Bool) -> [String] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf` String
str) [String
"ab",String
"cd",String
"pq",String
"xy"])
search :: (String -> Bool) -> String -> Bool
search :: (String -> Bool) -> String -> Bool
search String -> Bool
p = (String -> Bool) -> [String] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any String -> Bool
p ([String] -> Bool) -> (String -> [String]) -> String -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> [String]
forall a. [a] -> [[a]]
tails
pairTwice :: String -> Bool
pairTwice :: String -> Bool
pairTwice =
(String -> Bool) -> String -> Bool
search \case
Char
x:Char
y:String
z -> [Char
x,Char
y] String -> String -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf` String
z
String
_ -> Bool
False
nearby :: String -> Bool
nearby :: String -> Bool
nearby =
(String -> Bool) -> String -> Bool
search \case
Char
w:Char
_:Char
y:String
_ -> Char
w Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
y
String
_ -> Bool
False