1 -- Writeup at https://work.njae.me.uk/2021/12/19/advent-of-code-2021-day-17/
4 import qualified Data.Text.IO as TIO
5 import Data.Attoparsec.Text
6 import Control.Applicative
10 data Tree = Pair Tree Tree | Leaf Int
13 data Cxt = Top | L Cxt Tree | R Tree Cxt
16 -- type Context = [(Direction, Tree)]
17 -- data Direction = Lft | Rght
18 -- deriving (Show, Eq)
20 type Loc = (Tree, Cxt)
24 do text <- TIO.readFile "data/advent18.txt"
25 let numbers = successfulParse text
29 part1 numbers = magnitude total
30 where total = foldl1' snailAdd numbers
32 part2 numbers = maximum [ magnitude $ snailAdd a b
33 | a <- numbers, b <- numbers]
35 magnitude :: Tree -> Int
36 magnitude (Leaf n) = n
37 magnitude (Pair a b) = 3 * (magnitude a) + 2 * (magnitude b)
41 left (Pair l r, c) = (l, L c r)
44 right (Pair l r, c) = (r, R l c)
50 up (t, Top) = (t, Top)
51 up (t, L c r) = (Pair t r, c)
52 up (t, R l c) = (Pair l t, c)
56 upmost l = upmost (up l)
58 modify :: Loc -> (Tree -> Tree) -> Loc
59 modify (t, c) f = (f t, c)
62 explode :: Tree -> Maybe Tree
68 mp0 = pairAtDepth 4 num
70 ((Pair (Leaf nl) (Leaf nr)), _) = p0
71 p1 = case rightmostOnLeft p0 of
73 Just leftReg -> modify leftReg (\(Leaf n) -> Leaf (n + nl))
74 p2 = case pairAtDepthC 4 (upmost p1) >>= leftmostOnRight of
76 Just rightReg -> modify rightReg (\(Leaf n) -> Leaf (n + nr))
77 p3 = case pairAtDepthC 4 (upmost p2) of
79 Just centrePair -> modify centrePair (\_ -> Leaf 0)
82 pairAtDepth :: Int -> Tree -> Maybe Loc
83 pairAtDepth n t = pairAtDepthC n (top t)
85 pairAtDepthC :: Int -> Loc -> Maybe Loc
86 pairAtDepthC _ (Leaf _, _) = Nothing
87 pairAtDepthC 0 t@(Pair _ _, _) = Just t
88 pairAtDepthC n t@(Pair _ _, _) =
89 pairAtDepthC (n - 1) (left t) <|> pairAtDepthC (n - 1) (right t)
91 rightmostOnLeft :: Loc -> Maybe Loc
92 rightmostOnLeft (_, Top) = Nothing
93 rightmostOnLeft t@(_, L c r) = rightmostOnLeft $ up t
94 rightmostOnLeft t@(_, R l c) = Just $ rightmostNum $ left $ up t
96 rightmostNum :: Loc -> Loc
97 rightmostNum t@(Leaf _, _) = t
98 rightmostNum t@(Pair _ _, _) = rightmostNum $ right t
100 leftmostOnRight :: Loc -> Maybe Loc
101 leftmostOnRight (_, Top) = Nothing
102 leftmostOnRight t@(_, R l c) = leftmostOnRight $ up t
103 leftmostOnRight t@(_, L c r) = Just $ leftmostNum $ right $ up t
105 leftmostNum :: Loc -> Loc
106 leftmostNum t@(Leaf _, _) = t
107 leftmostNum t@(Pair _ _, _) = leftmostNum $ left t
109 split :: Tree -> Maybe Tree
120 n1 = modify n0 (\_ -> Pair (Leaf ln) (Leaf rn))
121 (num1, _) = upmost n1
123 splittable :: Tree -> Maybe Loc
124 splittable t = splittableC (top t)
126 splittableC :: Loc -> Maybe Loc
127 splittableC t@(Leaf n, _)
129 | otherwise = Nothing
130 splittableC t@(Pair _ _, _) = splittableC (left t) <|> splittableC (right t)
133 reduce :: Tree -> Tree
136 expl = case (explode num) of
138 Just eres -> reduce eres
139 splt = case (split expl) of
141 Just sres -> reduce sres
143 snailAdd :: Tree -> Tree -> Tree
144 snailAdd a b = reduce $ Pair a b
147 -- Parse the input file
149 sfNumbersP = sfNumberP `sepBy` endOfLine
151 sfNumberP = regularP <|> pairP
153 regularP = Leaf <$> decimal
154 pairP = Pair <$> ("[" *> sfNumberP) <*> ("," *> sfNumberP) <* "]"
156 -- successfulParse :: Text -> (Integer, [Maybe Integer])
157 successfulParse input =
158 case parseOnly sfNumbersP input of
159 Left _err -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err
160 Right numbers -> numbers