-- |
-- Module      : AOC.Challenge.Day02
-- License     : BSD3
--
-- Stability   : experimental
-- Portability : non-portable
--
-- Day 2.  See "AOC.Solver" for the types used in this module!

module AOC.Challenge.Day02 (
    day02a
  , day02b
  ) where

import           AOC.Common                 (countTrue, CharParser, parseLines)
import           AOC.Solver                 ((:~>)(..))
import           Control.DeepSeq            (NFData)
import           Control.Monad.Combinators  (some)
import           GHC.Generics               (Generic)
import           Text.Megaparsec            (anySingle)
import           Text.Megaparsec.Char       (char, space)
import           Text.Megaparsec.Char.Lexer (decimal)

data Policy = P
    { Policy -> Int
pIx1  :: Int
    , Policy -> Int
pIx2  :: Int
    , Policy -> Char
pChar :: Char
    , Policy -> String
pPass :: String
    }
  deriving (Int -> Policy -> ShowS
[Policy] -> ShowS
Policy -> String
(Int -> Policy -> ShowS)
-> (Policy -> String) -> ([Policy] -> ShowS) -> Show Policy
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Policy] -> ShowS
$cshowList :: [Policy] -> ShowS
show :: Policy -> String
$cshow :: Policy -> String
showsPrec :: Int -> Policy -> ShowS
$cshowsPrec :: Int -> Policy -> ShowS
Show, Policy -> Policy -> Bool
(Policy -> Policy -> Bool)
-> (Policy -> Policy -> Bool) -> Eq Policy
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Policy -> Policy -> Bool
$c/= :: Policy -> Policy -> Bool
== :: Policy -> Policy -> Bool
$c== :: Policy -> Policy -> Bool
Eq, Eq Policy
Eq Policy
-> (Policy -> Policy -> Ordering)
-> (Policy -> Policy -> Bool)
-> (Policy -> Policy -> Bool)
-> (Policy -> Policy -> Bool)
-> (Policy -> Policy -> Bool)
-> (Policy -> Policy -> Policy)
-> (Policy -> Policy -> Policy)
-> Ord Policy
Policy -> Policy -> Bool
Policy -> Policy -> Ordering
Policy -> Policy -> Policy
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Policy -> Policy -> Policy
$cmin :: Policy -> Policy -> Policy
max :: Policy -> Policy -> Policy
$cmax :: Policy -> Policy -> Policy
>= :: Policy -> Policy -> Bool
$c>= :: Policy -> Policy -> Bool
> :: Policy -> Policy -> Bool
$c> :: Policy -> Policy -> Bool
<= :: Policy -> Policy -> Bool
$c<= :: Policy -> Policy -> Bool
< :: Policy -> Policy -> Bool
$c< :: Policy -> Policy -> Bool
compare :: Policy -> Policy -> Ordering
$ccompare :: Policy -> Policy -> Ordering
Ord, (forall x. Policy -> Rep Policy x)
-> (forall x. Rep Policy x -> Policy) -> Generic Policy
forall x. Rep Policy x -> Policy
forall x. Policy -> Rep Policy x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Policy x -> Policy
$cfrom :: forall x. Policy -> Rep Policy x
Generic)
instance NFData Policy

policy :: CharParser Policy
policy :: CharParser Policy
policy = Int -> Int -> Char -> String -> Policy
P (Int -> Int -> Char -> String -> Policy)
-> ParsecT Void String Identity Int
-> ParsecT Void String Identity (Int -> Char -> String -> Policy)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Void String Identity Int
forall e s (m :: * -> *) a.
(MonadParsec e s m, Token s ~ Char, Num a) =>
m a
decimal
           ParsecT Void String Identity (Int -> Char -> String -> Policy)
-> ParsecT Void String Identity Int
-> ParsecT Void String Identity (Char -> String -> Policy)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Token String -> ParsecT Void String Identity (Token String)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
Token String
'-' ParsecT Void String Identity Char
-> ParsecT Void String Identity Int
-> ParsecT Void String Identity Int
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ParsecT Void String Identity Int
forall e s (m :: * -> *) a.
(MonadParsec e s m, Token s ~ Char, Num a) =>
m a
decimal)
           ParsecT Void String Identity (Char -> String -> Policy)
-> ParsecT Void String Identity Char
-> ParsecT Void String Identity (String -> Policy)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (ParsecT Void String Identity ()
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space ParsecT Void String Identity ()
-> ParsecT Void String Identity Char
-> ParsecT Void String Identity Char
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ParsecT Void String Identity Char
forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
anySingle)
           ParsecT Void String Identity (String -> Policy)
-> ParsecT Void String Identity String -> CharParser Policy
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Token String -> ParsecT Void String Identity (Token String)
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
Token s -> m (Token s)
char Char
Token String
':' ParsecT Void String Identity Char
-> ParsecT Void String Identity ()
-> ParsecT Void String Identity ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ParsecT Void String Identity ()
forall e s (m :: * -> *).
(MonadParsec e s m, Token s ~ Char) =>
m ()
space ParsecT Void String Identity ()
-> ParsecT Void String Identity String
-> ParsecT Void String Identity String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ParsecT Void String Identity Char
-> ParsecT Void String Identity String
forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
some ParsecT Void String Identity Char
forall e s (m :: * -> *). MonadParsec e s m => m (Token s)
anySingle)

validate1 :: Policy -> Bool
validate1 :: Policy -> Bool
validate1 P{Char
Int
String
pPass :: String
pChar :: Char
pIx2 :: Int
pIx1 :: Int
pPass :: Policy -> String
pChar :: Policy -> Char
pIx2 :: Policy -> Int
pIx1 :: Policy -> Int
..} = Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
pIx1 Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
pIx2
  where
    n :: Int
n = (Char -> Bool) -> String -> Int
forall (f :: * -> *) a. Foldable f => (a -> Bool) -> f a -> Int
countTrue (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
pChar) String
pPass

validate2 :: Policy -> Bool
validate2 :: Policy -> Bool
validate2 P{Char
Int
String
pPass :: String
pChar :: Char
pIx2 :: Int
pIx1 :: Int
pPass :: Policy -> String
pChar :: Policy -> Char
pIx2 :: Policy -> Int
pIx1 :: Policy -> Int
..} = Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
  where
    n :: Int
n = (Char -> Bool) -> String -> Int
forall (f :: * -> *) a. Foldable f => (a -> Bool) -> f a -> Int
countTrue (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
pChar) [String
pPass String -> Int -> Char
forall a. [a] -> Int -> a
!! (Int
pIx1 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1), String
pPass String -> Int -> Char
forall a. [a] -> Int -> a
!! (Int
pIx2 Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)]

day02a :: [Policy] :~> Int
day02a :: [Policy] :~> Int
day02a = MkSol :: forall a b.
(String -> Maybe a)
-> ((?dyno::DynoMap) => a -> Maybe b) -> (b -> String) -> a :~> b
MkSol
    { sParse :: String -> Maybe [Policy]
sParse = CharParser Policy -> String -> Maybe [Policy]
forall a. Parsec Void String a -> String -> Maybe [a]
parseLines CharParser Policy
policy
    , sShow :: Int -> String
sShow  = Int -> String
forall a. Show a => a -> String
show
    , sSolve :: (?dyno::DynoMap) => [Policy] -> Maybe Int
sSolve = Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> ([Policy] -> Int) -> [Policy] -> Maybe Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Policy -> Bool) -> [Policy] -> Int
forall (f :: * -> *) a. Foldable f => (a -> Bool) -> f a -> Int
countTrue Policy -> Bool
validate1
    }

day02b :: [Policy] :~> Int
day02b :: [Policy] :~> Int
day02b = MkSol :: forall a b.
(String -> Maybe a)
-> ((?dyno::DynoMap) => a -> Maybe b) -> (b -> String) -> a :~> b
MkSol
    { sParse :: String -> Maybe [Policy]
sParse = CharParser Policy -> String -> Maybe [Policy]
forall a. Parsec Void String a -> String -> Maybe [a]
parseLines CharParser Policy
policy
    , sShow :: Int -> String
sShow  = Int -> String
forall a. Show a => a -> String
show
    , sSolve :: (?dyno::DynoMap) => [Policy] -> Maybe Int
sSolve = Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> ([Policy] -> Int) -> [Policy] -> Maybe Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Policy -> Bool) -> [Policy] -> Int
forall (f :: * -> *) a. Foldable f => (a -> Bool) -> f a -> Int
countTrue Policy -> Bool
validate2
    }