1+ -- | Helper functions for parsing problem inputs.
12module ParseHelper where
23
34import Data.Char (isDigit )
@@ -9,62 +10,81 @@ import Text.ParserCombinators.ReadP
910import qualified GHC.Arr as A
1011
1112
13+ -- | Run a parser on each line of the input file.
1214parseInput :: Show x => ReadP x -> String -> [x ]
1315parseInput parser =
1416 parseInputRaw $ sepBy parser newline <* end
15- where
16- end = many $ choice [void newline, eof]
17+ where
18+ end = many $ choice [void newline, eof]
1719
20+
21+ -- | Run a parser on the full input file.
1822parseInputRaw :: Show x => ReadP x -> String -> x
1923parseInputRaw parser str =
2024 let results = readP_to_S parser str
2125 successes = filter ((== " " ) . snd ) results
2226 longestAttempts = sortOn (length . snd ) results
23- in case listToMaybe successes of
27+ in case listToMaybe successes of
2428 Nothing ->
2529 error $ " Parsing failure, longest attempt: " <> show (head longestAttempts)
2630 Just success ->
2731 fst success
2832
33+
34+ -- | Parse a newline or a carriage-return & newline.
2935newline :: ReadP Char
30- newline = choice
31- [ char ' \r ' *> char ' \n '
32- , char ' \n '
33- ]
36+ newline =
37+ choice
38+ [ char ' \r ' *> char ' \n '
39+ , char ' \n '
40+ ]
41+
3442
43+ -- | Parse a positive or negative integer.
3544parseInt :: ReadP Int
3645parseInt = do
3746 sign <- option 1 (char ' -' $> (- 1 ))
3847 (sign * ) . read <$> many1 (satisfy isDigit)
3948
4049
50+ -- | Parse a comma-separated array of ints, with optional beginning & end
51+ -- characters.
4152parseIntArray :: Maybe Char -> Maybe Char -> ReadP [Int ]
4253parseIntArray maybeStart maybeEnd = do
4354 mapM_ char maybeStart
4455 ints <- sepBy parseInt (skipSpaces *> char ' ,' *> skipSpaces)
4556 mapM_ char maybeEnd
4657 return ints
4758
59+
60+ -- | Parse a grid of digits with no column separators & rows separated by
61+ -- newlines.
4862parseIntGrid :: ReadP (A. Array (Int , Int ) Int )
4963parseIntGrid = do
5064 ls <- sepBy (many1 $ satisfy isDigit) newline <* newline
5165 let height = length ls
5266 width = minimum $ map length ls
53- return $ A. array ((0 , 0 ), (height - 1 , width - 1 ))
54- [ ((w, h), c)
55- | h <- [0 .. height - 1 ]
56- , w <- [0 .. width - 1 ]
57- , let c = read [ls !! h !! w]
58- ]
67+ return $
68+ A. array
69+ ((0 , 0 ), (height - 1 , width - 1 ))
70+ [ ((w, h), c)
71+ | h <- [0 .. height - 1 ]
72+ , w <- [0 .. width - 1 ]
73+ , let c = read [ls !! h !! w]
74+ ]
5975
76+
77+ -- | Parse a grid of characters.
6078parseCharGrid :: (Char -> Bool ) -> ReadP (A. Array (Int , Int ) Char )
6179parseCharGrid validChar = do
6280 ls <- sepBy (many1 $ satisfy validChar) newline
6381 let height = length ls
6482 width = minimum $ map length ls
65- return $ A. array ((0 , 0 ), (width - 1 , height - 1 ))
66- [ ((w, h), c)
67- | h <- [0 .. height - 1 ]
68- , w <- [0 .. width - 1 ]
69- , let c = ls !! h !! w
70- ]
83+ return $
84+ A. array
85+ ((0 , 0 ), (width - 1 , height - 1 ))
86+ [ ((w, h), c)
87+ | h <- [0 .. height - 1 ]
88+ , w <- [0 .. width - 1 ]
89+ , let c = ls !! h !! w
90+ ]
0 commit comments