61 lines
1.7 KiB
Haskell
61 lines
1.7 KiB
Haskell
import Data.List
|
|
|
|
main :: IO ()
|
|
main = do
|
|
input <- readFile "10/input.txt"
|
|
let x = lines input
|
|
-- Problem 1
|
|
print $ f x
|
|
-- Problem 2
|
|
print $ g x
|
|
where
|
|
f = solve 1
|
|
g = solve 2
|
|
|
|
-- | A syntax error type.
|
|
data Error = Incomplete Char
|
|
| Corrupted Char
|
|
deriving
|
|
Show
|
|
|
|
-- | Check if the error is that the found character doesn't match the
|
|
-- | expected character.
|
|
corrupted :: Error -> Bool
|
|
corrupted (Corrupted _) = True
|
|
corrupted _ = False
|
|
|
|
-- | Check if the error is that the line is incomplete.
|
|
incomplete :: Error -> Bool
|
|
incomplete = not . corrupted
|
|
|
|
solve :: Int -> [String] -> Int
|
|
solve 1 = sum . (>>= (map score . take 1 . filter corrupted . synck []))
|
|
solve 2 = mid . sort . map calc . filter (all incomplete) . map (synck [])
|
|
where
|
|
calc = foldl (\a e -> (a * 5) + score e) 0
|
|
mid ls = ls !! (length ls `div` 2)
|
|
|
|
-- | Run the syntax checker on the given line.
|
|
synck :: [Char] -- ^ A stack of expected characters
|
|
-> String -- ^ The remaining characters to check
|
|
-> [Error] -- ^ A list of syntax errors found for the given line
|
|
synck ex [] = map Incomplete ex
|
|
synck ex (x : xs)
|
|
| x == '<' = synck ('>' : ex) xs
|
|
| x == '{' = synck ('}' : ex) xs
|
|
| x == '(' = synck (')' : ex) xs
|
|
| x == '[' = synck (']' : ex) xs
|
|
| head ex == x = synck (tail ex) xs
|
|
| otherwise = Corrupted x : synck ex xs
|
|
|
|
-- | Score the severity of the error.
|
|
score :: Error -> Int
|
|
score (Corrupted ')') = 3
|
|
score (Corrupted ']') = 57
|
|
score (Corrupted '}') = 1197
|
|
score (Corrupted '>') = 25137
|
|
score (Incomplete ')') = 1
|
|
score (Incomplete ']') = 2
|
|
score (Incomplete '}') = 3
|
|
score (Incomplete '>') = 4
|