Better height field validation
[advent-of-code-20.git] / advent02 / src / advent02.hs
1 -- import Debug.Trace
2
3 import Data.Text (Text)
4 import qualified Data.Text.IO as TIO
5
6 import Data.Void (Void)
7
8 import Text.Megaparsec hiding (State)
9 import Text.Megaparsec.Char
10 import qualified Text.Megaparsec.Char.Lexer as L
11 import qualified Control.Applicative as CA
12
13 data Policy = Policy
14 { lower :: Int
15 , upper :: Int
16 , character :: Char
17 , password :: String
18 } deriving (Show, Eq, Ord)
19
20 main :: IO ()
21 main =
22 do text <- TIO.readFile "data/advent02.txt"
23 let policies = successfulParse text
24 print $ part1 policies
25 print $ part2 policies
26
27 part1 = length . filter inRange
28 where nCharsPresent p = length $ filter (== (character p)) (password p)
29 inRange p = (nCharsPresent p >= (lower p)) && (nCharsPresent p <= (upper p))
30
31 part2 = length . filter matches
32
33 matches p = ((pw!!l) == c) /= ((pw!!u) == c)
34 where pw = password p
35 c = character p
36 l = (lower p) - 1
37 u = (upper p) - 1
38
39
40 -- Parse the input file
41 type Parser = Parsec Void Text
42
43 sc :: Parser ()
44 sc = L.space space1 CA.empty CA.empty
45 -- sc = L.space (skipSome (char ' ')) CA.empty CA.empty
46
47 lexeme = L.lexeme sc
48 integerP = lexeme L.decimal
49 -- signedInteger = L.signed sc integer
50 symb = L.symbol sc
51 hyphenP = symb "-"
52 colonP = symb ":"
53 characterP = alphaNumChar <* sc
54 passwordP = some alphaNumChar <* sc
55
56 policiesP = many policyP
57 policyP = Policy <$> integerP <* hyphenP <*> integerP <*> characterP <* colonP <*> passwordP
58
59 successfulParse :: Text -> [Policy]
60 successfulParse input =
61 case parse policiesP "input" input of
62 Left _err -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err
63 Right policies -> policies