never executed always true always false
    1 {-|
    2 Module:      Y2015.D12
    3 Description: Advent of Code Day 12 Solutions.
    4 License:     MIT
    5 Maintainer:  @tylerjl
    6 
    7 Solutions to the day 12 set of problems for <adventofcode.com>.
    8 -}
    9 
   10 {-# LANGUAGE OverloadedStrings #-}
   11 
   12 module Y2015.D12 (jsonSum, jsonSumFixed) where
   13 
   14 import           Data.Aeson           (Value(..), decode)
   15 import           Data.ByteString.Lazy (ByteString)
   16 import           Data.Foldable        (foldl')
   17 import           Data.Scientific      (floatingOrInteger)
   18 import qualified Data.Vector          as V
   19 import qualified Data.HashMap.Strict as KM
   20 
   21 -- |Sum all numbers in a JSON-like structure
   22 jsonSum :: ByteString -- ^ JSON input string
   23         -> Int        -- ^ Summation of all nested numeric values
   24 jsonSum = jSum . decode
   25     where jSum Nothing  = 0
   26           jSum (Just v) = sumValue v
   27 
   28 -- |Sums all numbers in a JSON-like structure with a specific filter
   29 jsonSumFixed :: ByteString -- ^ JSON input string
   30              -> Int        -- ^ Summation of all nested numeric values
   31 jsonSumFixed = jSum . decode
   32     where jSum Nothing  = 0
   33           jSum (Just v) = sumValue $ filterV v
   34 
   35 filterV :: Value -> Value
   36 filterV o@(Object x) | r o    = Null
   37                      | otherwise  = Object (KM.map filterV x)
   38                      where r (String x') = x' == "red"
   39                            r (Object o') = any r $ KM.filter string  o'
   40                            r _          = False
   41                            string (String _) = True
   42                            string _          = False
   43 filterV (Array v)                 = Array (V.map filterV v)
   44 filterV s@(String x) | x == "red" = Null
   45                      | otherwise  = s
   46 filterV v                         = v
   47 
   48 sumValue :: Value -> Int
   49 sumValue (Object o) = foldl' valAcc 0 o
   50 sumValue (Number n) = case (floatingOrInteger n :: Either Double Int) of
   51                            Left _  -> 0
   52                            Right i -> i
   53 sumValue (Array n)  = V.foldl' valAcc 0 n
   54 sumValue _          = 0
   55 
   56 valAcc :: Int -> Value -> Int
   57 valAcc = flip ((+) . sumValue)