-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day03.hs
112 lines (94 loc) · 2.45 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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ViewPatterns #-}
module Day03 where
import Control.Arrow ((&&&))
import Control.Monad
import Data.Array (Array)
import Data.Bifunctor
import Data.Char
import Data.Either
import Data.Foldable
import Data.Function (on)
import Data.Functor
import Data.Map (Map)
import Data.Maybe
import Data.MultiSet (MultiSet)
import Data.Set (Set)
import Text.ParserCombinators.ReadP
import Harness
import ParseHelper
import Data.Array qualified as A
import Data.List qualified as L
import Data.Map qualified as M
import Data.MultiSet qualified as MS
import Data.Set qualified as S
import Debug.Trace
-- (parseInput lineParser) OR (parseInputRaw fullInputParser)
main :: IO ()
main = getInputAndSolve (parseInputRaw parseInstructions) runSimple runConditional
-- SOLVE
runSimple :: [Instruction] -> Int
runSimple =
sum
. map
( \case
Multiply {..} -> xVal * yVal
_ -> 0
)
runConditional :: [Instruction] -> Int
runConditional =
snd
. foldl'
( \(isEnabled, acc) -> \case
Do -> (True, acc)
Dont -> (False, acc)
Multiply {..} ->
if isEnabled
then
(isEnabled, xVal * yVal + acc)
else
(isEnabled, acc)
)
(True, 0)
-- HELPERS
-- PARSE
data Instruction
= Multiply
{ xVal :: !Int
, yVal :: !Int
}
| Dont
| Do
deriving (Show)
parseInstructions :: ReadP [Instruction]
parseInstructions = do
catMaybes
<$> manyTill
( (Just <$> parseMultiply)
<++ (Just <$> parseDoDont)
<++ ((satisfy (`notElem` "md") <++ get) $> Nothing)
)
eof
where
parseMultiply :: ReadP Instruction
parseMultiply = do
void $ string "mul("
xVal <- parseInt
void $ char ','
yVal <- parseInt
void $ char ')'
return Multiply {..}
parseDoDont :: ReadP Instruction
parseDoDont =
choice
[ string "don't()" $> Dont
, string "do()" $> Do
]