never executed always true always false
    1 {-|
    2 Module:      Y2021.D18
    3 Description: Advent of Code 2021 Day 18 Solutions.
    4 License:     MIT
    5 Maintainer:  @tylerjl
    6 
    7 Solutions to the 2021 day 18 set of problems for <adventofcode.com>.
    8 -}
    9 module Y2021.D18
   10   ( parse18
   11   , part18A
   12   , part18B
   13   ) where
   14 
   15 import Control.Applicative
   16 import Data.Attoparsec.Text hiding (take, takeWhile)
   17 import Data.Either.Utils           (fromRight)
   18 import Data.List                   (foldl1')
   19 import Data.Text                   (Text)
   20 
   21 data SnailTree
   22   = SnailNumber Int
   23   | SnailPair SnailTree SnailTree
   24   deriving Eq
   25 instance Show SnailTree where
   26   show (SnailNumber n) = show n
   27   show (SnailPair a b) = "[" <> show a <> "," <> show b <> "]"
   28 
   29 -- |Solution to part A
   30 part18A :: Text -> Int
   31 part18A = magnitude . reduce . foldl1' combine . map reduce . parse18
   32 
   33 combine :: SnailTree -> SnailTree -> SnailTree
   34 combine (reduce -> a) (reduce -> b) = snailAdd a b
   35 
   36 -- |Solution to part B
   37 part18B :: Text -> Int
   38 part18B (parse18 -> rows) =
   39   maximum [(magnitude . reduce) (combine x y) | x <- rows, y <- rows, x /= y]
   40 
   41 snailAdd :: SnailTree -> SnailTree -> SnailTree
   42 snailAdd = SnailPair
   43 
   44 magnitude :: SnailTree -> Int
   45 magnitude (SnailNumber n) = n
   46 magnitude (SnailPair (magnitude -> l) (magnitude -> r)) = l * 3 + r * 2
   47 
   48 explode :: SnailTree -> Either SnailTree SnailTree
   49 explode = either (\(_, tree, _) -> Left tree) Right . go (0 :: Int)
   50   where
   51     go _ (SnailNumber n) = pure (SnailNumber n)
   52     go d (SnailPair (SnailNumber l) (SnailNumber r)) | d >= 4 = Left (l, SnailNumber 0, r)
   53     go d (SnailPair l r) =
   54       case go (succ d) l of
   55         Left (ln, l', rn) -> Left (ln, SnailPair l' (withLeft r rn), 0)
   56         _ -> case go (succ d) r of
   57           Left (ln, r', rn) -> Left (0, SnailPair (withRight l ln) r', rn)
   58           _ -> pure $ SnailPair l r
   59     withLeft (SnailNumber v)  n = SnailNumber (v + n)
   60     withLeft (SnailPair l r)  n = SnailPair (withLeft l n) r
   61     withRight (SnailNumber v) n = SnailNumber (v + n)
   62     withRight (SnailPair l r) n = SnailPair l (withRight r n)
   63 
   64 split :: SnailTree -> Either SnailTree SnailTree
   65 split s@(SnailNumber n)
   66   | n >= 10 = Left $ SnailPair (SnailNumber $ n `div` 2) (SnailNumber $ succ n `div` 2)
   67   | otherwise = Right s
   68 split (SnailPair l r) =
   69   case split l of
   70     Left l' -> Left (SnailPair l' r)
   71     _ -> case split r of
   72       Left r' -> Left (SnailPair l r')
   73       _ -> Right $ SnailPair l r
   74 
   75 reduce :: SnailTree -> SnailTree
   76 reduce (explode -> Right (split -> Right tree)) = tree
   77 reduce (explode -> Right (split -> Left tree)) = reduce tree
   78 reduce (explode -> Left tree) = reduce tree
   79 
   80 -- |Parse.
   81 parse18 :: Text -> [SnailTree]
   82 parse18 = fromRight . parseOnly (parser <* atEnd)
   83   where
   84     parser = snail `sepBy1` endOfLine
   85     snail = SnailPair <$> (char '[' *> sv <* char ',') <*> (sv <* char ']')
   86     sv = (SnailNumber <$> decimal) <|> snail