+
+initialCache :: Record -> Cache
+initialCache (Record springs signature) = M.union lastOperational cache0
+ where cache0 = M.union sprs sigs
+ sprs = M.fromList $ fmap (\s -> (Record s [], 0)) $ tails springs
+ sigs = M.fromList $ fmap (\g -> (Record [] g, 0)) $ tails signature
+ lastOperationalChunk =
+ reverse $ takeWhile isPossOperational $ reverse springs
+ lastOperational =
+ M.fromList $ fmap (\s -> (Record s [], 1)) $ tails lastOperationalChunk
+
+isPossOperational :: Spring -> Bool
+isPossOperational Operational = True
+isPossOperational Unknown = True
+isPossOperational _ = False
+
+isPossDamaged :: Spring -> Bool
+isPossDamaged Damaged = True
+isPossDamaged Unknown = True
+isPossDamaged _ = False
+
+possibleDamagedChunk :: [Spring] -> Int -> Bool
+possibleDamagedChunk springs n =
+ isDamagedChunk && ((null afterChunk) || (possOperational $ head afterChunk))
+ where isDamagedChunk = (length $ filter isPossDamaged $ take n springs) == n
+ afterChunk = take 1 $ drop n springs
+
+
+-- countViable previousSprings (Record (s:springs) (g:signature)) =
+
+
+-- count: either consume this group or not
+
+
+-- cache is how many ways to assign unknowns, leaving this partial record.
+-- first item of springs is unknown or damaged
+-- count = count_consuming_group + count_leaving_group
+-- if first spring is damaged: count = count_consuming_group
+
+
+
+-- if first spring is damaged and next few springs can match next group:
+-- consume springs (including all following operational ones), consume group
+-- Add to cache: record' -> cache ! original
+-- return countViable record'
+-- if first spring is unknown
+-- assume it's damaged, consume springs, consume group
+