diff --git a/2023/12/Main2.hs b/2023/12/Main2.hs new file mode 100644 index 0000000..cd0da6c --- /dev/null +++ b/2023/12/Main2.hs @@ -0,0 +1,48 @@ +import Control.Monad (guard) +import Data.List.Split (splitOn) +import Data.Maybe (fromMaybe) +import qualified Data.Vector as V +import Data.Vector (Vector) + +nFolds :: Int +nFolds = 5 + +solve :: (Vector Int, Vector Char) -> Int +solve (records, fences) = getAt 0 0 + where + v = V.generate (V.length records + 1) + $ V.generate (V.length fences + 1) . getAt' + + getAt r f = v V.! r V.! f + + getAt' r f = maybe noFencesLeft getWithFence $ fences V.!? f + where + noFencesLeft + | r == V.length records = 1 + | otherwise = 0 + + getWithFence thisFence = worksHere thisFence + startBreakHere thisFence + + worksHere '#' = 0 + worksHere _ = getAt r (f + 1) + + startBreakHere '.' = 0 + startBreakHere _ = fromMaybe 0 + $ do + thisRecord <- records V.!? r + let remainingFences = V.drop f fences + fenceAfter <- remainingFences V.!? thisRecord + guard ('.' `notElem` V.take thisRecord remainingFences) + guard (fenceAfter /= '#') + return $ getAt (r + 1) (f + thisRecord + 1) + +parseLine :: String -> (Vector Int, Vector Char) +parseLine l = ( unfoldRecords . map read . splitOn "," $ y + , (`V.snoc` '.') . V.tail . unfoldRecords $ '?':x) + where + (x:y:_) = splitOn " " l + + unfoldRecords = V.concat . replicate nFolds . V.fromList + +main :: IO () +main = print . sum . map (solve . parseLine) . lines =<< readFile "data.txt"