Solve 2024-03

This commit is contained in:
Alexander Kobjolke 2024-12-04 00:31:57 +01:00
parent 656f4d82d8
commit c4d54a9757
5 changed files with 107 additions and 4 deletions

View file

@ -1,6 +1,98 @@
module AoC.Y2024.D03 (solve) where
module AoC.Y2024.D03 (solve, example1, example2) where
import Prelude hiding (many)
import AoC.Riddle
import Text.Regex.TDFA
type Program = [Statement]
data Statement
= Mul Int Int
| Disable
| Enable
deriving stock (Show)
-- | example data
--
-- >>> part1 example
-- 2
-- >>> part2 example
-- 4
example1 :: Text
example1 = "xmul(2,4)%&mul[3,7]!@^do_not_mul(5,5)+mul(32,64]then(mul(11,8)mul(8,5))"
example2 :: Text
example2 = "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"
parseStatement :: String -> Maybe Statement
parseStatement "do()" = Just Enable
parseStatement "don't()" = Just Disable
parseStatement ('m' : 'u' : 'l' : rest) =
let
xs = (rest =~ ("[0-9]{1,3}" :: String)) :: [[String]]
in
parseMul $ concat xs
parseStatement _ = Nothing
parseMul :: [String] -> Maybe Statement
parseMul [a, b] = Mul <$> readMaybe a <*> readMaybe b
parseMul _ = Nothing
regex :: String
regex = "(mul)\\(([0-9]{1,3}),([0-9]{1,3})\\)|(don\\'t)\\(\\)|(do)\\(\\)"
regex2 :: String
regex2 = "mul\\([0-9]{1,3},[0-9]{1,3}\\)|don't\\(\\)|do\\(\\)"
parsePart1 :: Riddle -> Program
parsePart1 riddle =
let
args = Prelude.concat (toString riddle =~ regex2 :: [[String]]) :: [String]
stmts = mapMaybe parseStatement args
in
stmts
-- int :: Parser Int
-- int = L.decimal
-- pMul :: Parser Statement
-- pMul = do
-- _ <- string "mul"
-- _ <- char '('
-- a <- int
-- _ <- char ','
-- b <- int
-- _ <- char ')'
-- pure $ Mul a b
-- pAny :: Parser ()
-- pAny = void (many (satisfy (const True)))
-- pPart1 :: Parser Program
-- pPart1 = many (many pAny *> try pMul)
evalPart1 :: Program -> Int
evalPart1 = foldl' eval 0
where
eval :: Int -> Statement -> Int
eval r (Mul a b) = r + a * b
eval r _ = r
evalPart2 :: Program -> Int
evalPart2 = snd . foldl' eval (True, 0)
where
eval :: (Bool, Int) -> Statement -> (Bool, Int)
eval (True, r) (Mul a b) = (True, r + a * b)
eval (False, r) (Mul _ _) = (False, r)
eval (_, r) Enable = (True, r)
eval (_, r) Disable = (False, r)
part1 :: Riddle -> Int
part1 = evalPart1 . parsePart1
part2 :: Riddle -> Int
part2 = evalPart2 . parsePart1
solve :: (MonadIO m) => Text -> m (Either Text Solution)
solve _ = pure $ Left "not yet implemented"
solve riddle = pure $ Right [fromIntegral $ part1 riddle, fromIntegral $ part2 riddle]