From e9fd31ce38d1d5ddd21bfd629c11d5b0c39308a3 Mon Sep 17 00:00:00 2001 From: eriedaberrie Date: Thu, 14 Dec 2023 00:36:26 -0800 Subject: [PATCH] 2023 day 12: star 2 Oh my god --- 2023/12/Main2.hs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 2023/12/Main2.hs diff --git a/2023/12/Main2.hs b/2023/12/Main2.hs new file mode 100644 index 0000000..fb9ca9e --- /dev/null +++ b/2023/12/Main2.hs @@ -0,0 +1,47 @@ +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 + + worksHere '#' = 0 + worksHere _ = getAt r (f + 1) + + 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"