46 lines
1.1 KiB
Haskell
46 lines
1.1 KiB
Haskell
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
|