diff options
author | Laura Orvokki Kursula <lav@vampires.gay> | 2024-12-03 22:07:13 +0100 |
---|---|---|
committer | Laura Orvokki Kursula <lav@vampires.gay> | 2024-12-03 22:07:13 +0100 |
commit | 6f5aea359c48942b43baa73e108801aea02b8a4a (patch) | |
tree | a0e5b387b19d24abc8c2da8202588eef6f6fb475 /3-2.hs | |
parent | c22c115e1faf469d2fcda7227ac5eed4b1e71fb5 (diff) | |
download | aoc2024-6f5aea359c48942b43baa73e108801aea02b8a4a.tar.gz aoc2024-6f5aea359c48942b43baa73e108801aea02b8a4a.zip |
3-2
Diffstat (limited to '3-2.hs')
-rw-r--r-- | 3-2.hs | 69 |
1 files changed, 69 insertions, 0 deletions
@@ -0,0 +1,69 @@ +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 + +exclude :: String -> String -> String -> String +exclude _ _ [] = [] +exclude from to s@(x:xs) = case parse (string from) s of + Nothing -> x : exclude from to xs + Just (_,b) -> exclude' from to b + +exclude' :: String -> String -> String -> String +exclude' _ _ [] = [] +exclude' from to s@(_:xs) = case parse (string to) s of + Nothing -> exclude' from to xs + Just (_,b) -> exclude from to 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 + let s' = exclude "don't()" "do()" s + print $ result s' |