-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay12.hs
101 lines (84 loc) · 2.51 KB
/
Day12.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
{-# LANGUAGE TemplateHaskell #-}
module Day12
( part1
, part2
) where
import Data.ByteString (ByteString)
import FlatParse.Basic (anyAsciiChar, anyAsciiDecimalInt,
char, eof, isDigit, optional_,
runParser, satisfy, skipSatisfy,
switch, (<|>))
import Helpers.Parsers.FlatParse (extract)
import qualified Helpers.Parsers.FlatParse as F (Parser)
type Parser = F.Parser Int
type ParserJ = F.Parser JSON
data JSON
= Object [(String, JSON)]
| Array [JSON]
| String String
| Number Int
deriving (Eq)
parseNumbers :: Parser
parseNumbers =
parseNegativeNumber
<|> parseNumber
<|> (skipSatisfy (not . isDigit) >> parseNumbers)
<|> (eof >> return 0)
parseNegativeNumber :: Parser
parseNegativeNumber = do
$(char '-')
number <- negate <$> anyAsciiDecimalInt
(+ number) <$> parseNumbers
parseNumber :: Parser
parseNumber = do
number <- anyAsciiDecimalInt
(number +) <$> parseNumbers
parseInput :: ParserJ
parseInput =
$(switch
[|case _ of
"{" -> Object <$> parseObject
"[" -> Array <$> parseArray
"\"" -> String <$> parseString
"-" -> Number . negate <$> anyAsciiDecimalInt
_ -> Number <$> anyAsciiDecimalInt|])
parseArray :: F.Parser [JSON]
parseArray =
$(switch
[|case _ of
"]" -> return []
_ -> parseContents|])
parseContents :: F.Parser [JSON]
parseContents = do
json <- parseInput
optional_ . skipSatisfy $ (== ',')
(json :) <$> parseArray
parseObject :: F.Parser [(String, JSON)]
parseObject =
$(switch
[|case _ of
"}" -> return []
_ -> parsePair|])
parsePair :: F.Parser [(String, JSON)]
parsePair = do
$(char '"')
key <- parseString
$(char ':')
json <- parseInput
optional_ . skipSatisfy $ (== ',')
((key, json) :) <$> parseObject
parseString :: F.Parser String
parseString =
(satisfy (== '"') >> return [])
<|> (anyAsciiChar >>= \x -> (x :) <$> parseString)
evaluate :: JSON -> Int
evaluate (String _) = 0
evaluate (Number n) = n
evaluate (Array a) = sum . map evaluate $ a
evaluate (Object o)
| "red" `elem` map fst o || String "red" `elem` map snd o = 0
| otherwise = sum . map (evaluate . snd) $ o
part1 :: Bool -> ByteString -> String
part1 _ = show . extract . runParser parseNumbers
part2 :: Bool -> ByteString -> String
part2 _ = show . evaluate . extract . runParser parseInput