62 lines
1.9 KiB
Haskell
62 lines
1.9 KiB
Haskell
module Main (main) where
|
|
|
|
import Lib.Parser (Parser (parse), separated, char, parens, string, number, satisfy)
|
|
import Control.Applicative (Alternative (..))
|
|
import Data.Maybe (fromJust, catMaybes)
|
|
|
|
-- | Part 1
|
|
data MulOper = MulOper Int Int deriving (Show, Eq)
|
|
|
|
perform :: MulOper -> Int
|
|
perform (MulOper a b) = a * b
|
|
|
|
mulOper :: Parser MulOper
|
|
mulOper = (\_ [a, b] -> MulOper a b) <$> string "mul" <*> parens (char ',' `separated` number)
|
|
|
|
manyMaybeMulOper :: Parser [Maybe MulOper]
|
|
manyMaybeMulOper = many $ Just <$> mulOper <|> Nothing <$ satisfy (const True)
|
|
|
|
extractMulOps :: Maybe ([Maybe MulOper], String) -> [MulOper]
|
|
extractMulOps = catMaybes . fst . fromJust
|
|
|
|
part1 :: String -> IO ()
|
|
part1 s = print $ sum $ map perform $ extractMulOps $ parse manyMaybeMulOper s
|
|
|
|
-- | Part 2
|
|
data Token
|
|
= EnableAction
|
|
| DisableAction
|
|
| MulAction MulOper
|
|
deriving (Show, Eq)
|
|
|
|
doOper :: Parser Token
|
|
doOper = EnableAction <$ string "do()"
|
|
|
|
dontOper :: Parser Token
|
|
dontOper = DisableAction <$ string "don't()"
|
|
|
|
wrapMulOper :: Parser Token
|
|
wrapMulOper = MulAction <$> mulOper
|
|
|
|
manyMaybeToken :: Parser [Maybe Token]
|
|
manyMaybeToken = many $ Just <$> (doOper <|> dontOper <|> wrapMulOper) <|> Nothing <$ satisfy (const True)
|
|
|
|
runCommands :: [Token] -> Int
|
|
runCommands tokens = runCommands' tokens True 0
|
|
where
|
|
runCommands' :: [Token] -> Bool -> Int -> Int
|
|
runCommands' [] _ s = s
|
|
runCommands' ((MulAction _):cs) False s = s + runCommands' cs False s
|
|
runCommands' ((MulAction (MulOper a b)):cs) True s = s + a * b + runCommands' cs True s
|
|
runCommands' (EnableAction:cs) _ s = s + runCommands' cs True s
|
|
runCommands' (DisableAction:cs) _ s = s + runCommands' cs False s
|
|
|
|
extractTokens :: Maybe ([Maybe Token], String) -> [Token]
|
|
extractTokens = catMaybes . fst . fromJust
|
|
|
|
part2 :: String -> IO()
|
|
part2 s = print $ runCommands $ extractTokens $ parse manyMaybeToken s
|
|
|
|
-- | Main
|
|
main :: IO ()
|
|
main = readFile "resources/day3.txt" >>= part2
|