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 _ -> ((p !! a) == t) /= ((p !! b) == t) where a = (pred a') b = (pred b') parse :: String -> Maybe Password parse [] = Nothing 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 inBounds :: Int -> Int -> String -> (Bool, Bool) inBounds a b s = ( len >= a, len >= b ) where len = length s