advent-of-code/2023/haskell/solutions/Day12.hs

80 lines
2 KiB
Haskell
Raw Normal View History

2023-12-16 21:53:51 +01:00
{-# LANGUAGE OverloadedStrings #-}
module Day12 where
import Data.Void (Void)
import Data.Text (Text)
2023-12-17 00:00:31 +01:00
import Data.List (intercalate)
2023-12-16 21:53:51 +01:00
import Text.Megaparsec (Parsec, errorBundlePretty, runParser, many, eof, choice, sepBy)
2023-12-17 00:00:31 +01:00
import Data.Bifunctor (first, bimap)
2023-12-16 21:53:51 +01:00
import Text.Megaparsec.Char (char, space, newline)
import Text.Megaparsec.Char.Lexer (decimal)
data Cell
= U -- ? unknown
| O -- . operational
| D -- # damaged
2023-12-16 23:46:21 +01:00
deriving (Show, Eq)
2023-12-16 21:53:51 +01:00
type Row = ([Cell], [Int])
type Parser = Parsec Void Text
input :: Text
input =
"???.### 1,1,3\n\
\.??..??...?##. 1,1,3\n\
\?#?#?#?#?#?#?#? 1,3,1,6\n\
\????.#...#... 4,1,1\n\
\????.######..#####. 1,6,5\n\
\?###???????? 3,2,1\n"
parse :: Text -> Either String [Row]
parse = first errorBundlePretty . runParser rows ""
where
cell :: Parser Cell
cell = choice [U <$ char '?', O <$ char '.', D <$ char '#']
row :: Parser Row
row = do
cs <- many cell <* space
ns <- decimal `sepBy` char ',' <* newline
return (cs, ns)
rows :: Parser [Row]
rows = many row <* eof
arrange :: [Cell] -> [Int] -> [[Cell]]
2023-12-16 23:46:21 +01:00
arrange [] [] = [[]]
arrange [] _ = []
arrange cs []
| D `notElem` cs = [map (const O) cs]
| otherwise = []
arrange cs@(c:cr) ns@(n:nr)
| canFill && canSkip = tryFill <> trySkip
| canFill = tryFill
| canSkip = trySkip
| otherwise = []
where
(window, rest) = splitAt n cs
fill :: [Cell] -> [Cell]
fill = (replicate n D ++)
canSkip :: Bool
canSkip = c /= D
trySkip :: [[Cell]]
trySkip = map (O:) (arrange cr ns)
canFill :: Bool
canFill = O `notElem` window && n == length window && (null rest || head rest /= D)
tryFill :: [[Cell]]
tryFill
| null rest = map fill (arrange rest nr)
| otherwise = map (fill . (O:)) (arrange (tail rest) nr)
2023-12-16 21:53:51 +01:00
solveA :: [Row] -> Int
solveA = length . concatMap (uncurry arrange)
2023-12-17 00:00:31 +01:00
unfold :: Row -> Row
unfold = bimap (intercalate [U] . replicate 5) (concat . replicate 5)
2023-12-16 21:53:51 +01:00
2023-12-17 00:00:31 +01:00
solveB :: [Row] -> Int
solveB = solveA . map unfold . take 5