adventofcode-2021/10/syntaxchecker.hs

96 lines
2.4 KiB
Haskell

import Data.List (foldl', sort)
main :: IO ()
main = do
input <- getContents
let
code = lines input
(putStrLn . show . solution1) code
(putStrLn . show . solution2) code
solution1 :: [String] -> Int
solution1 = sum . map charScore . map (head . fst . resolveChunks)
where
charScore :: Char -> Int
charScore ')' = 3
charScore ']' = 57
charScore '}' = 1197
charScore '>' = 25137
charScore _ = 0
solution2 :: [String] -> Int
solution2 = middle . sort . map score . completed . nonCorrupt
where
completed = map (completeChunks . fst)
nonCorrupt = filter notCorrupt . map resolveChunks
score :: [Char] -> Int
score = foldl' (\s x -> s * 5 + (charScore x)) 0
where
charScore :: Char -> Int
charScore ')' = 1
charScore ']' = 2
charScore '}' = 3
charScore '>' = 4
charScore _ = undefined
notCorrupt :: ([Char], Bool) -> Bool
notCorrupt (_, corrupt) = not corrupt
middle :: [a] -> a
middle [] = undefined
middle l = l !! (length l `quot` 2)
completeChunks :: String -> String
completeChunks = map close
where
close :: Char -> Char
close c
| c == '(' = ')'
| c == '[' = ']'
| c == '{' = '}'
| c == '<' = '>'
| otherwise = undefined
resolveChunks :: String -> ([Char], Bool)
resolveChunks = foldl' resolve ([], False)
where
resolve :: ([Char], Bool) -> Char -> ([Char], Bool)
resolve (stack, broken) c
| broken = (stack, broken)
| isOpen c = (c:stack, False)
| close c == head stack = (tail stack, False)
| close c /= head stack = (c:stack, True)
| otherwise = undefined
isOpen :: Char -> Bool
isOpen c
| c == '(' = True
| c == '[' = True
| c == '{' = True
| c == '<' = True
| otherwise = False
close :: Char -> Char
close c
| c == ')' = '('
| c == ']' = '['
| c == '}' = '{'
| c == '>' = '<'
| otherwise = undefined
-- Tests
testInput = [
"[({(<(())[]>[[{[]{<()<>>",
"[(()[<>])]({[<{<<[]>>(",
"{([(<{}[<>[]}>{[]{[(<()>",
"(((({<>}<{<{<>}{[]{[]{}",
"[[<[([]))<([[{}[[()]]]",
"[{[{({}]{}}([{[{{{}}([]",
"{<[[]]>}<{[{[{[]{()[[[]",
"[<(<(<(<{}))><([]([]()",
"<{([([[(<>()){}]>(<<{{",
"<{([{{}}[<[[[<>{}]]]>[]]"
]
test1 = solution1 testInput -- 26397
test2 = solution2 testInput -- 288957