import Data.Char (digitToInt)
import Debug.Trace
data E = N Int | P E E
instance Show E where
show (N a ) = show a
show (P a b) = '[' : show a ++ (',' : show b) ++ "]"
split :: E -> Either E E
split (N a) | a > 9 = Right $ div2 a
| a <= 9 = Left $ N a
where div2 x = let (a, b) = (x `div` 2, x - a)
in P (N a) (N b)
split (P a b) = case split a of
Left c -> case split b of
Left d -> Left $ P c d
Right d -> Right $ P c d
Right c -> Right $ P c b
explode :: Int -> E -> Either E (E, (Int, Int))
explode l e@(N _) = Left e
explode l e@(P (N a) (N b)) | l >= 4 = Right ((N 0), (a, b))
| otherwise = Left e
explode l (P (P a b) (P c d)) = case explode (l + 2) a of
Left m -> case explode (l + 2) b of
Left n -> case explode (l + 2) c of
Left o -> case explode (l + 2) d of
Left p
-> Left (P (P m n) (P o p))
Right (p, (x, y))
-> Right (P (P m n) (P (addRight x o) p), (0, y))
Right (o, (x, y))
-> Right (P (P m (addRight x n)) (P o (addLeft y d)), (0, 0))
Right (n, (x, y))
-> Right (P (P (addRight x m) n) (P (addLeft y c) d), (0, 0))
Right (m, (x, y))
-> Right (P (P m (addLeft y b)) (P c d), (x, 0))
explode l (P (P a b) c) = case explode (l + 2) a of
Left d -> case explode (l + 2) b of
Left e -> Left (P (P d e) c)
Right (e, (x, y))
-> Right (P (P (addRight x d) e) (addLeft y c), (0, 0))
Right (d, (x, y))
-> Right (P (P d (addLeft y b)) c, (x, 0))
explode l (P a (P b c)) = case explode (l + 2) b of
Left e -> case explode (l + 2) c of
Left f
-> Left (P a (P e f))
Right (f, (x, y))
-> Right (P a (P (addRight x e) f), (0, y))
Right (e, (x, y))
-> Right (P (addRight x a) (P e (addLeft y c)), (0, 0))
addLeft n (P a b) = P (addLeft n a) b
addLeft n (N a ) = N $ a + n
addRight n (P a b) = P a (addRight n b)
addRight n (N b ) = N $ b + n
explode' e
| Left g <- f = g
| Right (e, _) <- f = explode' e
where f = explode 0 e
reduce e
| Left g <- f = g
| Right g <- f = reduce g
where f = split $ explode' e
add a b = reduce (P a b)
parse :: String -> (E, String)
parse ('[':l:',':r:']':s)= (P (N $ digitToInt l) (N $ digitToInt r), s)
parse ('[':l:',':s) = (P (N $ digitToInt l) r, s')
where (r, (']':s')) = parse s
parse ('[':s@('[':_)) = (P l r, s'')
where (l, (',':s')) = parse s
(r, (']':s'')) = parse s'
parse ('[':s) = (l, s')
where (l, (']':s')) = parse s
parse (x:s) | '0' <= x && x <= '9' = (N $ digitToInt x, s)
parse s = error (show s)
magnitude (N a ) = a
magnitude (P a b) = magnitude a * 3 + magnitude b * 2
magnitudes s = maximum $ map magnitude $ concat $ map g [0..length s - 1]
where f i = let (l, (_:r)) = splitAt i s in l ++ r
g i = map (add (s !! i)) $ f i
main = map (fst . parse) <$> lines <$> readFile "input.txt"
>>= \s@(e:es) -> (print $ magnitude $ foldl add e es)
>> (print $ magnitudes $ s)