• # Solution en Haskell

    Posté par . En réponse au message Advent of Code 2023, jour 12. Évalué à 4.

    Solution en Haskell par programmation dynamique.
    La partie 1 prend 5ms et la partie 2 prend 30ms

    import AOC.Prelude
    import AOC (aoc)
    import AOC.Parser (Parser, sepEndBy1, some, eol, decimal, hspace)
    import qualified Data.Vector as V
    import Data.Array (listArray, range, (!))
    data Spring = Operational | Damaged | Unknown deriving (Eq, Show)
    type Row = ([Spring], [Int])
    parser :: Parser [Row]
    parser = row `sepEndBy1` eol where
     row = (,) <$> some spring <* hspace <*> decimal `sepEndBy1` ","
     spring = Operational <$ "." <|> Damaged <$ "#" <|> Unknown <$ "?"
    countArrangements :: Row -> Integer
    countArrangements (springs, groups) = arr ! (0, 0) where
     vsprings = V.fromList (springs ++ [Operational])
     springsLength = V.length vsprings
     vGroups = V.fromList groups
     groupsLength = V.length vGroups
     nextOperational = V.generate springsLength \i ->
     if vsprings V.! i == Operational then i else nextOperational V.! (i+1)
     arr = listArray bds [
     let currentSpring = vsprings V.! pos
     currentGroupSize = vGroups V.! groupPos
     in
     if pos == springsLength then
     if groupPos == groupsLength then 1 else 0
     else
     let nextOp = nextOperational V.! pos
     pos' = pos + currentGroupSize
     x = if currentSpring /= Damaged then arr ! (pos + 1, groupPos) else 0
     y = if groupPos < groupsLength && nextOp >= pos' && vsprings V.! pos' /= Damaged
     then arr ! (pos' + 1, groupPos + 1)
     else 0
     in x + y
     | (pos, groupPos) <- range bds
     ]
     bds = ((0, 0), (springsLength, groupsLength))
    part1 :: [Row] -> Integer
    part1 = sum . map countArrangements
    part2 :: [Row] -> Integer
    part2 = sum . map (countArrangements . unfold) where
     unfold = bimap (intercalate [Unknown] . replicate 5) (concat . replicate 5)