|
|
@@ -0,0 +1,63 @@ |
|
|
|
data Password = Password Int Int Char String |
|
|
|
deriving Show |
|
|
|
|
|
|
|
main :: IO () |
|
|
|
main = do |
|
|
|
raw <- readFile "day2.txt" |
|
|
|
let ls = map parse $ lines raw |
|
|
|
fs = case (sequence ls) of |
|
|
|
Nothing -> error "invalid input" |
|
|
|
(Just ps) -> ps |
|
|
|
ansA = length $ filter (== True) $ map validA fs |
|
|
|
ansB = length $ filter (== True) $ map validB fs |
|
|
|
in do |
|
|
|
putStrLn $ "day2a: " ++ (show ansA) |
|
|
|
putStrLn $ "day2b: " ++ (show ansB) |
|
|
|
|
|
|
|
validA :: Password -> Bool |
|
|
|
validA (Password l u t p) = |
|
|
|
let len = length $ filter (== t) p |
|
|
|
in (len >= l) |
|
|
|
&& (len <= u) |
|
|
|
|
|
|
|
validB :: Password -> Bool |
|
|
|
validB (Password a' b' t p) = |
|
|
|
case (inBounds a b p) of |
|
|
|
(False,False) -> False |
|
|
|
(True,False) -> (p !! a) == t |
|
|
|
(False,True) -> (p !! b) == t |
|
|
|
_ -> xor ((p !! a) == t) ((p !! b) == t) |
|
|
|
where |
|
|
|
a = (pred a') |
|
|
|
b = (pred b') |
|
|
|
|
|
|
|
parse :: String -> Maybe Password |
|
|
|
parse [] = error "empty password" |
|
|
|
parse s = |
|
|
|
do (l,s') <- parseInt s |
|
|
|
(u,s'') <- parseInt $ dropChar s' |
|
|
|
(t,s''') <- parseChar $ dropChar s'' |
|
|
|
let p = (dropChar . dropChar) s''' |
|
|
|
in (Just $ Password l u t p) |
|
|
|
|
|
|
|
parseInt :: String -> Maybe (Int,String) |
|
|
|
parseInt s = case (reads s) of |
|
|
|
[] -> Nothing |
|
|
|
[a] -> Just a |
|
|
|
|
|
|
|
parseChar :: String -> Maybe (Char,String) |
|
|
|
parseChar [] = Nothing |
|
|
|
parseChar (t:s) = Just (t,s) |
|
|
|
|
|
|
|
dropChar :: String -> String |
|
|
|
dropChar [] = [] |
|
|
|
dropChar (_:ls) = ls |
|
|
|
|
|
|
|
xor :: Bool -> Bool -> Bool |
|
|
|
xor True False = True |
|
|
|
xor False True = True |
|
|
|
xor _ _ = False |
|
|
|
|
|
|
|
inBounds :: Int -> Int -> String -> (Bool, Bool) |
|
|
|
inBounds a b s = ( len >= a, len >= b ) |
|
|
|
where len = length s |