2023-08-27 22:30:00 +02:00
|
|
|
{-# LANGUAGE ImportQualifiedPost #-}
|
|
|
|
|
|
|
|
|
|
module Parse where
|
|
|
|
|
|
2023-08-30 09:32:12 +02:00
|
|
|
import Common
|
2023-08-30 12:22:06 +02:00
|
|
|
import Data.Char (digitToInt)
|
2023-08-30 09:32:12 +02:00
|
|
|
import Data.Function ((&))
|
|
|
|
|
import Data.Text qualified as T
|
|
|
|
|
import Data.Void
|
2023-08-27 22:30:00 +02:00
|
|
|
import Text.Megaparsec qualified as M
|
2023-08-30 12:22:06 +02:00
|
|
|
import Text.Megaparsec.Char (digitChar)
|
2023-08-27 22:30:00 +02:00
|
|
|
import Text.Megaparsec.Char qualified as MC
|
|
|
|
|
import Text.Megaparsec.Char.Lexer qualified as MCL
|
2023-08-30 09:32:12 +02:00
|
|
|
import Util (both)
|
2023-08-27 22:30:00 +02:00
|
|
|
|
2023-09-18 11:33:52 +02:00
|
|
|
import Data.List (transpose)
|
|
|
|
|
import Data.List.Extra (chunksOf)
|
|
|
|
|
|
|
|
|
|
import Data.Map (Map)
|
|
|
|
|
import Data.Map qualified as M
|
|
|
|
|
import Data.Maybe (fromMaybe)
|
|
|
|
|
|
2023-08-30 12:22:06 +02:00
|
|
|
type Parser = M.Parsec Void T.Text
|
|
|
|
|
|
2023-08-27 22:30:00 +02:00
|
|
|
someLines :: Parser a -> Parser [a]
|
|
|
|
|
someLines p = p `M.sepEndBy1` MC.newline
|
|
|
|
|
|
|
|
|
|
number :: Parser Int
|
2023-08-30 09:32:12 +02:00
|
|
|
number = MCL.decimal
|
|
|
|
|
|
2023-09-18 11:33:52 +02:00
|
|
|
int :: Parser Int
|
|
|
|
|
int = MCL.signed (pure ()) number
|
|
|
|
|
|
2023-08-30 12:22:06 +02:00
|
|
|
digit :: Parser Int
|
|
|
|
|
digit = digitToInt <$> digitChar
|
2023-08-30 09:32:12 +02:00
|
|
|
|
|
|
|
|
parsecDay ::
|
|
|
|
|
Parser a ->
|
|
|
|
|
(a -> Result, a -> Result) ->
|
|
|
|
|
Day
|
|
|
|
|
parsecDay parser parts =
|
|
|
|
|
ParsecDay
|
|
|
|
|
( \path text ->
|
|
|
|
|
( case M.parse (parser <* M.eof) path text of
|
|
|
|
|
Left e -> Left $ M.errorBundlePretty e
|
|
|
|
|
Right parsedInput -> Right $ both (parsedInput &) parts
|
|
|
|
|
)
|
|
|
|
|
)
|
2023-09-18 11:33:52 +02:00
|
|
|
|
|
|
|
|
parseCRT :: [String] -> String
|
|
|
|
|
parseCRT = map (\grid -> fromMaybe '?' (M.lookup grid gridToChar)) . slice
|
|
|
|
|
where
|
|
|
|
|
slice :: [String] -> [[String]]
|
|
|
|
|
slice = transpose . map (chunksOf 5)
|
|
|
|
|
|
|
|
|
|
gridToChar :: Map [String] Char
|
|
|
|
|
gridToChar =
|
|
|
|
|
M.fromList
|
|
|
|
|
[
|
|
|
|
|
(
|
|
|
|
|
[ ".##.."
|
|
|
|
|
, "#..#."
|
|
|
|
|
, "#..#."
|
|
|
|
|
, "####."
|
|
|
|
|
, "#..#."
|
|
|
|
|
, "#..#."
|
|
|
|
|
]
|
|
|
|
|
, 'A'
|
|
|
|
|
)
|
|
|
|
|
,
|
|
|
|
|
(
|
|
|
|
|
[ "###.."
|
|
|
|
|
, "#..#."
|
|
|
|
|
, "###.."
|
|
|
|
|
, "#..#."
|
|
|
|
|
, "#..#."
|
|
|
|
|
, "###.."
|
|
|
|
|
]
|
|
|
|
|
, 'B'
|
|
|
|
|
)
|
|
|
|
|
,
|
|
|
|
|
(
|
|
|
|
|
[ "#...."
|
|
|
|
|
, "#...."
|
|
|
|
|
, "#...."
|
|
|
|
|
, "#...."
|
|
|
|
|
, "#...."
|
|
|
|
|
, "####."
|
|
|
|
|
]
|
|
|
|
|
, 'L'
|
|
|
|
|
)
|
|
|
|
|
,
|
|
|
|
|
(
|
|
|
|
|
[ "###.."
|
|
|
|
|
, "#..#."
|
|
|
|
|
, "#..#."
|
|
|
|
|
, "###.."
|
|
|
|
|
, "#...."
|
|
|
|
|
, "#...."
|
|
|
|
|
]
|
|
|
|
|
, 'P'
|
|
|
|
|
)
|
|
|
|
|
,
|
|
|
|
|
(
|
|
|
|
|
[ "#..#."
|
|
|
|
|
, "#..#."
|
|
|
|
|
, "#..#."
|
|
|
|
|
, "#..#."
|
|
|
|
|
, "#..#."
|
|
|
|
|
, ".##.."
|
|
|
|
|
]
|
|
|
|
|
, 'U'
|
|
|
|
|
)
|
|
|
|
|
,
|
|
|
|
|
(
|
|
|
|
|
[ "####."
|
|
|
|
|
, "...#."
|
|
|
|
|
, "..#.."
|
|
|
|
|
, ".#..."
|
|
|
|
|
, "#...."
|
|
|
|
|
, "####."
|
|
|
|
|
]
|
|
|
|
|
, 'Z'
|
|
|
|
|
)
|
|
|
|
|
]
|