aoc-2021/day10/second.hs

59 lines
1.3 KiB
Haskell

import Data.List (sort)
type Parser = Char -> Maybe Char
median :: Integral a => [a] -> a
median xs = xs !! mid
where len = length xs
mid = div len 2
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 cs = aux 0 cs
where aux res [] = res
aux x (c:cs) = aux (x * 5 + (delimScore c)) cs
delimScore :: Char -> Integer
delimScore c = case c of
')' -> 1
']' -> 2
'}' -> 3
'>' -> 4
_ -> 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 :: [Char] -> String -> [Char]
parseLine closers [] = closers
parseLine closers (c:str)
| openDelim c = parseLine (mapOpenClose c:closers) str
| closingDelim c = case p c of
Just _ -> []
Nothing -> parseLine (tail closers) str
where p = parseChar (head closers)
solution :: [String] -> Integer
solution = median
. sort
. map score
. filter (/="")
. (map $ parseLine [])
-- main = interact $ show . solution . lines