包含テストでサブセットを生成する簡単なプログラムをテストしています。たとえば、与えられた
*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)]]
包含テストは次のとおりです。タプルのメンバーの最初の部分には、null 交差が必要です。
機能することがテストされると、各サブセットの内積snd
を累積するのではなく合計することが計画されます。
以前に同様の質問をしたことがあるので、再帰が [2,3] で分岐するときに、スキップされたセクションを通過すると、2 つ目の分岐が同じ可能性を超えて実行されるため、余分な分岐が生成されると思います。それを解決する方法についての指針をいただければ幸いです。また、そのような製品の組み合わせをより効率的に列挙して合計する方法についてのアイデアを共有したい場合も、それは素晴らしいことです.
Haskell コード:
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