-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrun.hs
56 lines (44 loc) · 1.07 KB
/
run.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
import Data.Void (Void)
import Text.Megaparsec
import Text.Megaparsec.Char
type Parser = Parsec Void String
right :: (Show a) => Either a b -> b
right (Left x) = error $ show x
right (Right x) = x
data DataStream = Group [DataStream]
| Garbage Int
deriving (Show, Eq, Ord)
groupP :: Parser DataStream
groupP = do
char '{'
inner <- sepBy streamP (char ',')
char '}'
pure $ Group inner
garbageP :: Parser DataStream
garbageP = do
char '<'
count <- eat
pure $ Garbage count
eat :: Parser Int
eat = eat' 0
eat' :: Int -> Parser Int
eat' i = do
c <- asciiChar
case c of
'>' -> pure i
'!' -> asciiChar *> eat' i
_ -> eat' (i + 1)
streamP :: Parser DataStream
streamP = groupP <|> garbageP
parser :: Parser DataStream
parser = streamP <* eof
part1 = go 1
where go _ (Garbage _) = 0
go i (Group gs) = i + sum (map (go (i+1)) gs)
part2 = go
where go (Garbage c) = c
go (Group gs) = sum (map go gs)
main = do
input <- right . parse parser "" . head . lines <$> readFile "input.txt"
print $ part1 input
print $ part2 input