type Parser = Char -> Maybe Char parseChar :: Char -> Parser parseChar c x | c == x = Nothing | otherwise = Just x mapOpenClose :: Char -> Char mapOpenClose c = case c of '(' -> ')' '[' -> ']' '{' -> '}' '<' -> '>' _ -> error "not element in map" score :: Char -> Integer score c = case c of ')' -> 3 ']' -> 57 '}' -> 1197 '>' -> 25137 _ -> 0 openDelim c = (c=='(') || (c=='[') || (c=='{') || (c=='<') closingDelim c = (c==')') || (c==']') || (c=='}') || (c=='>') -- Keep stack of parse functions. Apply the top one on any closing delimeter, -- check for Just x. parseLine :: [Parser] -> String -> Char parseLine _ [] = ' ' parseLine parsers (c:str) | openDelim c = parseLine ((parseChar $ mapOpenClose c):parsers) str | closingDelim c = case p c of Just _ -> c Nothing -> parseLine (tail parsers) str where p = head parsers solution :: [String] -> Integer solution = foldr (+) 0 . map score . filter (/=' ') -- painful, I blame Haskell's lack of proper sum types . (map $ parseLine []) main = interact $ show . solution . lines