64 lines
1.6 KiB
Haskell
64 lines
1.6 KiB
Haskell
|
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
|