diff options
Diffstat (limited to 'execs')
-rw-r--r-- | execs/Day02.hs | 50 |
1 files changed, 28 insertions, 22 deletions
diff --git a/execs/Day02.hs b/execs/Day02.hs index bcb0896..87c90ec 100644 --- a/execs/Day02.hs +++ b/execs/Day02.hs | |||
@@ -1,39 +1,45 @@ | |||
1 | module Main where | 1 | module Main where |
2 | 2 | ||
3 | import Data.Char | 3 | import Data.Char |
4 | import Data.Either | ||
4 | import Control.Monad | 5 | import Control.Monad |
6 | import Text.ParserCombinators.Parsec | ||
7 | import Text.Parsec.Char | ||
5 | 8 | ||
6 | countElem :: (Eq a) => a -> [a] -> Int | ||
7 | countElem c ls = sum $ map (fromEnum . (== c)) ls | 9 | countElem c ls = sum $ map (fromEnum . (== c)) ls |
8 | 10 | ||
9 | xor :: Bool -> Bool -> Bool | 11 | xor a b = (not a && b) || (a && not b) |
10 | xor True True = False | ||
11 | xor True False = True | ||
12 | xor False True = True | ||
13 | xor False False = False | ||
14 | 12 | ||
15 | ranges :: [String] -> (Int, Int) | 13 | right (Right a) = a |
16 | ranges r = | ||
17 | let p = head r | ||
18 | start = read $ takeWhile (/= '-') p | ||
19 | end = abs . read $ dropWhile (/= '-') p | ||
20 | in (start, end) | ||
21 | 14 | ||
22 | charac :: [String] -> Char | 15 | data PassProp = PassProp |
23 | charac s = head (s !! 1) | 16 | { range :: (Int, Int) |
17 | , c :: Char | ||
18 | , pass :: String | ||
19 | } deriving (Show) | ||
24 | 20 | ||
25 | pass :: [String] -> String | 21 | parseProp :: Parser PassProp |
26 | pass = last | 22 | parseProp = do |
23 | lower <- many1 digit | ||
24 | upper <- char '-' >> many1 digit | ||
25 | c <- space >> letter | ||
26 | password <- string ": " >> many letter | ||
27 | return $ PassProp (read lower, read upper) c password | ||
27 | 28 | ||
28 | doCheck1 :: ((Int, Int), Char , String) -> Bool | 29 | doCheck1 :: PassProp -> Bool |
29 | doCheck1 ((lower, upper), c, pass) = count >= lower && count <= upper | 30 | doCheck1 PassProp { range = (lower, upper), c = c, pass = pass} = |
30 | where count = countElem c pass | 31 | count >= lower && count <= upper |
32 | where count = countElem c pass | ||
31 | 33 | ||
32 | doCheck2 :: ((Int, Int), Char , String) -> Bool | 34 | doCheck2 :: PassProp -> Bool |
33 | doCheck2 ((lower, upper), c, pass) = (pass !! (lower - 1) == c) `xor` (pass !! (upper - 1) == c) | 35 | doCheck2 PassProp { range = (lower, upper), c = c, pass = pass} = |
36 | (pass !! (lower - 1) == c) `xor` (pass !! (upper - 1) == c) | ||
37 | |||
38 | parseLine :: Parser a -> String -> a | ||
39 | parseLine parser line = right $ parse parser "input" line | ||
34 | 40 | ||
35 | main :: IO () | 41 | main :: IO () |
36 | main = do | 42 | main = do |
37 | n <- map (fromEnum . doCheck2 . (\w -> (ranges w, charac w, pass w)) . words) . lines <$> readFile "input/02" | 43 | n <- map (fromEnum . doCheck2 . parseLine parseProp) . lines <$> readFile "input/02" |
38 | print $ sum n | 44 | print $ sum n |
39 | 45 | ||