diff options
| author | Laura Orvokki Kursula <lav@vampires.gay> | 2024-12-03 22:07:09 +0100 | 
|---|---|---|
| committer | Laura Orvokki Kursula <lav@vampires.gay> | 2024-12-03 22:07:09 +0100 | 
| commit | c22c115e1faf469d2fcda7227ac5eed4b1e71fb5 (patch) | |
| tree | ad0d4998e08426ba696824f65686b1755633b2f4 | |
| parent | 1c8ec4bd5515d90f75a5d98adbab810a81522890 (diff) | |
| download | aoc2024-c22c115e1faf469d2fcda7227ac5eed4b1e71fb5.tar.gz aoc2024-c22c115e1faf469d2fcda7227ac5eed4b1e71fb5.zip | |
3-1
| -rw-r--r-- | 3-1.hs | 57 | 
1 files changed, 57 insertions, 0 deletions
| @@ -0,0 +1,57 @@ +import Data.Bifunctor +import Data.Char + +newtype Parser a b = Parser {parse :: a -> Maybe (b,a)} + +instance Functor (Parser a) where +  fmap f p = Parser (fmap (first f) . parse p) + +instance Monoid a => Applicative (Parser a) where +  pure x = Parser . const . Just $ (x, mempty) +  p <*> q = Parser $ \ x -> let r = parse p x +    in case r of +         Nothing    -> Nothing +         Just (a,b) -> let s = parse q b +           in case s of +                Nothing    -> Nothing +                Just (c,d) -> Just (a c, d) + +string :: String -> Parser String String +string s = Parser $ \ r -> if take (length s) r == s +                           then Just (s, drop (length s) r) +                           else Nothing + +while :: (a -> Bool) -> Parser [a] [a] +while p = Parser $ \ xs -> case while' xs of +                             ([], _) -> Nothing +                             a -> Just a +  where +    while' [] = ([], []) +    while' (x:xs) | p x = first (x:) (while' xs) +                  | otherwise = ([], x:xs) + + +number :: Parser String Integer +number = read <$> while isDigit + +scan :: Parser [a] b -> [a] -> [b] +scan _ [] = [] +scan p s@(_:xs) = case parse p s of +  Nothing    -> scan p xs +  Just (a,b) -> a : scan p b + +instruction :: Parser String (Integer, Integer) +instruction = (,) +  <$  string "mul(" +  <*> number +  <*  string "," +  <*> number +  <*  string ")" + +result :: String -> Integer +result = sum . map (uncurry (*)) . scan instruction + +main :: IO () +main = do +  s <- getContents +  print $ result s |