import Data.List import Data.List.Split import Data.Maybe import qualified Data.Text as T main :: IO () main = do let toDigit = T.unpack . T.replace (T.pack "10") (T.pack ":") . T.pack input <- map (map toDigit . lines) . splitOn "\n\n" <$> readFile "input" print $ sum $ zipWith (*) [1 ..] $ map (fromEnum . isOrdered 0) input let divider = ["[[6]]", "[[2]]"] let sorted = sortBy mySort (divider ++ concat input) print $ product $ map (+ 1) $ mapMaybe (`elemIndex` sorted) divider isOrdered :: Int -> [String] -> Bool isOrdered n [l:ls, r:rs] | n < 0 && l == ',' = False | n > 0 && r == ',' = True | l == r = isOrdered n [ls, rs] | l == ']' = (r /= ',') || isOrdered (succ n) [ls, r : rs] | r == ']' = l == ',' && isOrdered (pred n) [l : ls, rs] | l == '[' = r /= ']' && isOrdered (pred n) [ls, r : rs] | r == '[' = l == ']' || isOrdered (succ n) [l : ls, rs] | l > r = False | l < r = True | otherwise = False isOrdered _ [[], _] = True isOrdered _ [_, []] = False isOrdered _ _ = True addBrackets :: [String] -> [String] -> [String] addBrackets [accl,accr] [l:ls,r:rs] | l == r = addBrackets [l:accl,r:accr] [ls,rs] | l `elem` ['0'..':'] && r `elem` ['0' .. ':'] = addBrackets [l:accl,r:accr] [ls,rs] | l == '[' = addBrackets [l:accl,l:accr] [ls,r:rs] | r == '[' = addBrackets [r:accl,r:accr] [l:ls,rs] | l == ']' = addBrackets [accl,r:accr] [l:ls,rs] | r == ']' = addBrackets [l:accl,accr] [ls,r:rs] addBrackets [accl,accr] ["",rs]= map reverse [accl,reverse rs ++ accr] addBrackets [accl,accr] [ls,""] = map reverse [reverse ls ++ accl,accr] addBrackets _ acc = map reverse acc mySort :: String -> String -> Ordering mySort x y = if isOrdered 0 (addBrackets ["",""] [x, y]) then LT else GT