-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day03.hs
71 lines (58 loc) · 1.77 KB
/
Day03.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
module Main where
import Advent.Parser (Parser, runParser)
import Advent.Parser qualified as P
import Advent.Utils (run)
import Control.Applicative (Alternative (..))
type Input = String
data Inst = Do | Dont | Mul Int Int
deriving (Eq, Show)
testInput :: Input
testInput =
prepare
[ "xmul(2,4)&mul[3,7]!^don't()_mul(5,5)+mul(32,64](mul(11,8)undo()?mul(8,5))"
]
evalMul :: Inst -> Int
evalMul (Mul x y) = x * y
evalMul _ = 0
mulParser :: Parser Char Inst
mulParser = do
_ <- P.string "mul("
x <- P.integer
_ <- P.char ','
y <- P.integer
_ <- P.char ')'
return (Mul x y)
doParser :: Parser Char Inst
doParser = Do <$ P.string "do()"
dontParser :: Parser Char Inst
dontParser = Dont <$ P.string "don't()"
instParser :: Parser Char Inst
instParser = mulParser <|> doParser <|> dontParser
part1 :: Input -> Int
part1 ls = sum $ evalMul <$> findMuls [] ls
where
findMuls :: [Inst] -> String -> [Inst]
findMuls acc [] = acc
findMuls acc str =
case runParser mulParser str of
(Left _) -> findMuls acc (tail str)
(Right (m, rest)) -> findMuls (m : acc) rest
part2 :: Input -> Int
part2 ls = sum $ evalMul <$> findMuls True [] ls
where
findMuls :: Bool -> [Inst] -> String -> [Inst]
findMuls _ acc [] = acc
findMuls on acc str =
case runParser instParser str of
(Left _) -> findMuls on acc (tail str)
(Right (m, rest)) -> case m of
Do -> findMuls True acc rest
Dont -> findMuls False acc rest
_ ->
if on
then findMuls on (m : acc) rest
else findMuls on acc rest
prepare :: [String] -> Input
prepare = unlines
main :: IO ()
main = run part1 part2 prepare