2010-11-30 57 views
8

我使用Mathematica 7,用combinatorica包功能,我可以從元素,其中的順序無所謂的名單獲得一定數量的所有組合並沒有repetition.eg:組合與重複

in: KSubsets[{a, b, c, d}, 3] 
out: {{a, b, c}, {a, b, d}, {a, c, d}, {b, c, d}} 

我找不到一個函數,它會給出我從訂單無關緊要的元素列表中的某個數字的所有組合,並且重複。即上述示例將在輸出中包括諸如{a,a,b},{a,a,a},{b,b,b}等等的元素。

它可能需要自定義功能。如果我能想出一個答案,我會發佈一個答案,但現在我沒有看到明顯的解決方案。

編輯: 理想情況下,輸出不包含組合的重複,例如, 元組[{a,b,c,d},3] 將返回一個列表,其中包含兩個元素,如{a,a,b}和{b,a,a} ,從組合的角度來看,相同。

回答

7
DeleteDuplicates[Map[Sort, Tuples[{a, b, c, d}, 3]]] 
+0

請注意`Sort [#]&`與'Sort'相同。 – dreeves 2010-12-01 15:53:30

10

您可以將每個組合編碼爲{na,nb,nc,nd},其中na表示出現a的次數。然後,任務是查找4個非負整數的所有可能組合,總和最多爲3. IntegerPartition提供了一種快速方式來生成所有這樣的組合,其順序無關緊要,您可以按照Permutations的順序來跟蹤它以考慮不同的訂單

vars = {a, b, c, d}; 
len = 3; 
coef2vars[lst_] := 
Join @@ (MapIndexed[Table[vars[[#2[[1]]]], {#1}] &, lst]) 
coefs = Permutations /@ 
    IntegerPartitions[len, {Length[vars]}, Range[0, len]]; 
coef2vars /@ Flatten[coefs, 1] 

只是爲了好玩,在這裏選擇的時機IntegerPartitions和元組之間的比較完成這個任務,在數秒

approach1[numTypes_, len_] := 
    Union[Sort /@ Tuples[Range[numTypes], len]]; 
approach2[numTypes_, len_] := 
    Flatten[Permutations /@ 
    IntegerPartitions[len, {numTypes}, Range[0, len]], 1]; 

plot1 = ListLinePlot[(AbsoluteTiming[approach1[3, #];] // First // 
     Log) & /@ Range[13], PlotStyle -> Red]; 
plot2 = ListLinePlot[(AbsoluteTiming[approach2[3, #];] // First // 
     Log) & /@ Range[13]]; 
Show[plot1, plot2] 

http://yaroslavvb.com/upload/save/tuples-vs-partitions.png

+0

爲什麼這個否決? – Simon 2010-12-01 02:54:48

+0

看起來可能太複雜了? – 2010-12-01 02:56:23

2

在優雅的方法稍加改變由高性能馬克給出:

Select[Tuples[{a, b, c, d}, 3], OrderedQ] 

排列的方法是更爲通用的(但不是你要找的是什麼?)

例如:

Select[Permutations[ 
    [email protected]@ConstantArray[{a, b, c, d}, {3}], {2, 3}], OrderedQ] 

給出以下內容

alt text

編輯:

Select[Tuples[[email protected]{a, b, d, c}, 3], OrderedQ] 

可能是更好

編輯-2

當然,也可以使用案例。例如

Cases[Permutations[ 
    [email protected]@ConstantArray[{a, b, d, c}, {3}], {2, 3}], _?OrderedQ] 

編輯-3。

如果列表包含重複元素,兩種方法將有所不同。從 輸出下面(方法2)中,例如,將包含重複(其可以或可以不被期望的):

Select[Tuples[{a, b, c, d, a}, 3], OrderedQ] 

它們可以容易地被排除:

[email protected][Tuples[{a, b, c, d, a}, 3], OrderedQ] 

的以下的計算結果爲「真」(刪除從呈現接近2列表重複的元素,並顯示結果的方法1(高性能標記方法)中產生的列表:

lst = RandomInteger[9, 50]; 
Select[[email protected]@Tuples[lst, 3], OrderedQ] == 
[email protected]tes[Map[Sort, Tuples[lst, 3]]] 

一樣噸他跟隨(從方法2的輸出中刪除重複,方法1的排序輸出):

lst = RandomInteger[9, 50]; 
[email protected][[email protected][lst, 3], OrderedQ] == 
[email protected][Map[Sort, Tuples[lst, 3]]] 

對不起!

1

這是一個簡單的解決方案,利用Mathetmatica的內置函數子集,因此在簡單性和性能之間取得了很好的平衡。在[n + k-1]的k個子集和[n]的k個組合與重複之間存在簡單的雙射。該功能將子集更改爲重複組合。

CombWithRep[n_, k_] := #-(Range[k]-1)&/@Subsets[Range[n+k-1],{k}] 

所以

CombWithRep[4,2] 

產生

{{1,1},{1,2},{1,3},{1,4},{2,2},{2,3},{2,4},{3,3},{3,4},{4,4}}