50 lines
1.4 KiB
Haskell
50 lines
1.4 KiB
Haskell
|
module Main where
|
||
|
|
||
|
import System.Environment (getArgs)
|
||
|
import Control.Monad (void)
|
||
|
|
||
|
import Text.Parsec (Parsec, try, (<|>), skipMany, anyChar, many, manyTill, parse, string, char)
|
||
|
import Text.ParserCombinators.Parsec (GenParser, eof)
|
||
|
import Text.ParserCombinators.Parsec.Number (decimal)
|
||
|
|
||
|
type Report = [Level]
|
||
|
type Level = Int
|
||
|
|
||
|
mul :: GenParser Char st (Int, Int)
|
||
|
mul = do
|
||
|
_ <- string "mul("
|
||
|
l <- decimal
|
||
|
_ <- char ','
|
||
|
r <- decimal
|
||
|
_ <- char ')';
|
||
|
return (l, r)
|
||
|
|
||
|
allMuls :: GenParser Char () [(Int, Int)]
|
||
|
allMuls = many loop
|
||
|
where
|
||
|
loop = try mul <|> try (anyChar >> loop)
|
||
|
|
||
|
dont :: GenParser Char () ()
|
||
|
dont = void $ try $ string "don't()" >> manyTill anyChar (try (eof <|> void (string "do()")))
|
||
|
|
||
|
allMulsConditional :: GenParser Char () [(Int, Int)]
|
||
|
allMulsConditional = many loop
|
||
|
where
|
||
|
loop = try (skipMany dont >> (try mul <|> try (anyChar >> loop)))
|
||
|
|
||
|
solve :: FilePath -> Parsec [Char] () [(Int, Int)] -> IO Int
|
||
|
solve fp parser = do
|
||
|
content <- readFile fp
|
||
|
case parse parser fp content of
|
||
|
Right m -> return $ sum $ map (uncurry (*)) m
|
||
|
Left e -> fail $ "Oh no! : " ++ show e
|
||
|
|
||
|
main :: IO ()
|
||
|
main = do
|
||
|
args <- getArgs
|
||
|
(fp:_) <- return args
|
||
|
resPart1 <- solve fp allMuls
|
||
|
resPart2 <- solve fp allMulsConditional
|
||
|
putStrLn ("Solution (Part 1) : " ++ show resPart1)
|
||
|
putStrLn ("Solution (Part 2) : " ++ show resPart2)
|