我正在测试一个简单的程序来生成包含测试的子集。例如,给定
*Main Data.List> factorsets 7
[([2],2),([2,3],1),([3],1),([5],1),([7],1)]
打电话chooseP 3 (factorsets 7)
,我想得到(从右到左读,a la cons
)
[[([5],1),([3],1),([2],2)]
,[([7],1),([3],1),([2],2)]
,[([7],1),([5],1),([2],2)]
,[([7],1),([5],1),([2,3],1)]
,[([7],1),([5],1),([3],1)]]
但是我的程序正在返回一个额外的[([7],1),([5],1),([3],1)]
(并且缺少一个[([7],1),([5],1),([2],2)]
):
[[([5],1),([3],1),([2],2)]
,[([7],1),([3],1),([2],2)]
,[([7],1),([5],1),([3],1)]
,[([7],1),([5],1),([2,3],1)]
,[([7],1),([5],1),([3],1)]]
包含测试是:成员的元组的第一部分必须有一个空交集。
一旦测试为工作,计划是对每个子集的内部乘积求和snd
,而不是累加它们。
由于我之前问过类似的问题,我想会生成一个额外的分支,因为当递归在 [2,3] 处分裂时,第二个分支一旦通过跳过的部分就会运行相同的可能性。任何有关如何解决该问题的指示将不胜感激;如果您想分享有关如何更有效地枚举和汇总此类产品组合的想法,那也很棒。
哈斯克尔代码:
chooseP k xs = chooseP' xs [] 0 where
chooseP' [] product count = if count == k then [product] else []
chooseP' yys product count
| count == k = [product]
| null yys = []
| otherwise = f ++ g
where (y:ys) = yys
(factorsY,numY) = y
f = let zzs = dropWhile (\(fs,ns) -> not . and . map (null . intersect fs . fst) $ product) yys
in if null zzs
then chooseP' [] product count
else let (z:zs) = zzs in chooseP' zs (z:product) (count + 1)
g = if and . map (null . intersect factorsY . fst) $ product
then chooseP' ys product count
else chooseP' ys [] 0