e9fd31ce38
Oh my god
48 lines
1.4 KiB
Haskell
48 lines
1.4 KiB
Haskell
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"
|