Both parts of the problem ask us to count how many passwords satisfy some validation function based on a policy. We create a datatype for a password and its associated policy as follows.
data Password = Password Int Int Char String
deriving (Eq, Show)
instance Read Password where
readPrec = lift $ do
min' <- read <$> munch1 isDigit
_ <- char '-'
max' <- read <$> munch1 isDigit
skipSpaces
c <- get
_ <- char ':'
skipSpaces
pw <- many get
pure $ Password min' max' c pw
Here we use the ReadP
type parser because they are much more easier to work with than old style parsers. Plus
we can perform some data validation on them too to ensure our input is correctly formatted.
Next, validating part A is as simple as counting how many characters in the password are equal to the one we want and
comparing the count.
validateA :: Password -> Bool
validateA (Password l h c p) = n >= l && n <= h
where n = length $ filter (==c) p
For part B, we use the ix
traversal to safely index into our password in case it is too short and check to see
if the characters are equal. The given condition is also equivalent to boolean XOR.
validateB :: Password -> Bool
validateB (Password l h c p) = first `xor` second
where first = p ^? ix (l - 1) == Just c
second = p ^? ix (h - 1) == Just c