{-# Language QuasiQuotes, BlockArguments #-}
module Main where
import Advent (format)
import Control.Monad (guard)
import Data.List (isInfixOf, tails)
main :: IO ()
IO ()
main =
do [[[Char]]]
xs <- [format|2016 7 ((%a*)&(]|[)%n)*|]
Int -> IO ()
forall a. Show a => a -> IO ()
print ([[[Char]]] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (([[Char]] -> Bool) -> [[[Char]]] -> [[[Char]]]
forall a. (a -> Bool) -> [a] -> [a]
filter [[Char]] -> Bool
supportsTLS [[[Char]]]
xs))
Int -> IO ()
forall a. Show a => a -> IO ()
print ([[[Char]]] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (([[Char]] -> Bool) -> [[[Char]]] -> [[[Char]]]
forall a. (a -> Bool) -> [a] -> [a]
filter [[Char]] -> Bool
supportsSSL [[[Char]]]
xs))
split :: [String] -> ([String], [String])
split :: [[Char]] -> ([[Char]], [[Char]])
split [] = ([],[])
split [[Char]
x] = ([[Char]
x],[])
split ([Char]
x:[Char]
y:[[Char]]
z) =
case [[Char]] -> ([[Char]], [[Char]])
split [[Char]]
z of
([[Char]]
a,[[Char]]
b) -> ([Char]
x[Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
:[[Char]]
a,[Char]
y[Char] -> [[Char]] -> [[Char]]
forall a. a -> [a] -> [a]
:[[Char]]
b)
supportsTLS :: [String] -> Bool
supportsTLS :: [[Char]] -> Bool
supportsTLS [[Char]]
xs =
case [[Char]] -> ([[Char]], [[Char]])
split [[Char]]
xs of
([[Char]]
supers, [[Char]]
hypers) -> ([Char] -> Bool) -> [[Char]] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any [Char] -> Bool
forall {a}. Eq a => [a] -> Bool
hasABBA [[Char]]
supers Bool -> Bool -> Bool
&& Bool -> Bool
not (([Char] -> Bool) -> [[Char]] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any [Char] -> Bool
forall {a}. Eq a => [a] -> Bool
hasABBA [[Char]]
hypers)
where
hasABBA :: [a] -> Bool
hasABBA [a]
ys = ([a] -> Bool) -> [[a]] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any [a] -> Bool
forall {a}. Eq a => [a] -> Bool
isABBA ([a] -> [[a]]
forall a. [a] -> [[a]]
tails [a]
ys)
isABBA :: [a] -> Bool
isABBA (a
w:a
x:a
y:a
z:[a]
_) = a
w a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
z Bool -> Bool -> Bool
&& a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
y Bool -> Bool -> Bool
&& a
w a -> a -> Bool
forall a. Eq a => a -> a -> Bool
/= a
x
isABBA [a]
_ = Bool
False
supportsSSL :: [String] -> Bool
supportsSSL :: [[Char]] -> Bool
supportsSSL [[Char]]
xs =
case [[Char]] -> ([[Char]], [[Char]])
split [[Char]]
xs of
([[Char]]
supers, [[Char]]
hypers) ->
Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [()] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null
do [Char]
s <- [[Char]]
supers
Char
x:Char
y:Char
z:[Char]
_ <- [Char] -> [[Char]]
forall a. [a] -> [[a]]
tails [Char]
s
Bool -> [()]
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
z Bool -> Bool -> Bool
&& Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
y)
[Char]
h <- [[Char]]
hypers
Bool -> [()]
forall (f :: * -> *). Alternative f => Bool -> f ()
guard ( [Char
y,Char
x,Char
y] [Char] -> [Char] -> Bool
forall a. Eq a => [a] -> [a] -> Bool
`isInfixOf` [Char]
h )