{-# LANGUAGE OverloadedStrings, QuasiQuotes #-}
module Main where
import Advent (format)
import Control.Applicative (Alternative((<|>)))
import Text.ParserCombinators.ReadP (ReadP, between, readS_to_P, sepBy)
main :: IO ()
IO ()
main =
do Value
value <- [format|2015 12 @p%n|]
Int -> IO ()
forall a. Show a => a -> IO ()
print (Value -> Int
numbers Value
value)
Int -> IO ()
forall a. Show a => a -> IO ()
print (Value -> Int
nonredNumbers Value
value)
p :: ReadP Value
p :: ReadP Value
p =
[Value] -> Value
Object ([Value] -> Value) -> ReadP [Value] -> ReadP Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP String -> ReadP String -> ReadP [Value] -> ReadP [Value]
forall open close a.
ReadP open -> ReadP close -> ReadP a -> ReadP a
between ReadP String
"{" ReadP String
"}" (ReadP Value
pEntry ReadP Value -> ReadP String -> ReadP [Value]
forall a sep. ReadP a -> ReadP sep -> ReadP [a]
`sepBy` ReadP String
",") ReadP Value -> ReadP Value -> ReadP Value
forall a. ReadP a -> ReadP a -> ReadP a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
[Value] -> Value
Array ([Value] -> Value) -> ReadP [Value] -> ReadP Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP String -> ReadP String -> ReadP [Value] -> ReadP [Value]
forall open close a.
ReadP open -> ReadP close -> ReadP a -> ReadP a
between ReadP String
"[" ReadP String
"]" (ReadP Value
p ReadP Value -> ReadP String -> ReadP [Value]
forall a sep. ReadP a -> ReadP sep -> ReadP [a]
`sepBy` ReadP String
",") ReadP Value -> ReadP Value -> ReadP Value
forall a. ReadP a -> ReadP a -> ReadP a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
String -> Value
String (String -> Value) -> ReadP String -> ReadP Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadP String
pString ReadP Value -> ReadP Value -> ReadP Value
forall a. ReadP a -> ReadP a -> ReadP a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
Int -> Value
Number (Int -> Value) -> ReadP Int -> ReadP Value
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReadS Int -> ReadP Int
forall a. ReadS a -> ReadP a
readS_to_P ReadS Int
forall a. Read a => ReadS a
reads
pString :: ReadP String
pString :: ReadP String
pString = ReadS String -> ReadP String
forall a. ReadS a -> ReadP a
readS_to_P ReadS String
forall a. Read a => ReadS a
reads
pEntry :: ReadP Value
pEntry :: ReadP Value
pEntry = ReadP String
pString ReadP String -> ReadP String -> ReadP String
forall a b. ReadP a -> ReadP b -> ReadP b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ReadP String
":" ReadP String -> ReadP Value -> ReadP Value
forall a b. ReadP a -> ReadP b -> ReadP b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ReadP Value
p
numbers :: Value -> Int
numbers :: Value -> Int
numbers Value
v =
case Value
v of
Number Int
n -> Int
n
Object [Value]
o -> [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((Value -> Int) -> [Value] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Value -> Int
numbers [Value]
o)
Array [Value]
a -> [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((Value -> Int) -> [Value] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Value -> Int
numbers [Value]
a)
String String
_ -> Int
0
nonredNumbers :: Value -> Int
nonredNumbers :: Value -> Int
nonredNumbers Value
v =
case Value
v of
Number Int
n -> Int
n
Object [Value]
o | String -> Value
String String
"red" Value -> [Value] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Value]
o -> [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((Value -> Int) -> [Value] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Value -> Int
nonredNumbers [Value]
o)
Array [Value]
a -> [Int] -> Int
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum ((Value -> Int) -> [Value] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Value -> Int
nonredNumbers [Value]
a)
Value
_ -> Int
0
data Value
= Number !Int
| Array [Value]
| Object [Value]
| String String
deriving (Value -> Value -> Bool
(Value -> Value -> Bool) -> (Value -> Value -> Bool) -> Eq Value
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Value -> Value -> Bool
== :: Value -> Value -> Bool
$c/= :: Value -> Value -> Bool
/= :: Value -> Value -> Bool
Eq, Eq Value
Eq Value =>
(Value -> Value -> Ordering)
-> (Value -> Value -> Bool)
-> (Value -> Value -> Bool)
-> (Value -> Value -> Bool)
-> (Value -> Value -> Bool)
-> (Value -> Value -> Value)
-> (Value -> Value -> Value)
-> Ord Value
Value -> Value -> Bool
Value -> Value -> Ordering
Value -> Value -> Value
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Value -> Value -> Ordering
compare :: Value -> Value -> Ordering
$c< :: Value -> Value -> Bool
< :: Value -> Value -> Bool
$c<= :: Value -> Value -> Bool
<= :: Value -> Value -> Bool
$c> :: Value -> Value -> Bool
> :: Value -> Value -> Bool
$c>= :: Value -> Value -> Bool
>= :: Value -> Value -> Bool
$cmax :: Value -> Value -> Value
max :: Value -> Value -> Value
$cmin :: Value -> Value -> Value
min :: Value -> Value -> Value
Ord, Int -> Value -> ShowS
[Value] -> ShowS
Value -> String
(Int -> Value -> ShowS)
-> (Value -> String) -> ([Value] -> ShowS) -> Show Value
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Value -> ShowS
showsPrec :: Int -> Value -> ShowS
$cshow :: Value -> String
show :: Value -> String
$cshowList :: [Value] -> ShowS
showList :: [Value] -> ShowS
Show)