2010-11-30 7 views
8

私はMathematica 7とcombinatoricaのパッケージ関数を使用しています。順序は関係ありません。繰り返しはありません:繰り返しを使った組み合わせ

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} ...などの要素が含まれています。

カスタム機能が必要な場合があります。私が1つを思いつくことができるなら、私は答えを掲示するだろうが、今のところ明らかな解決策は見当たらない。

編集: 出力には組み合わせの重複が含まれないことが理想的です。 タプル[{a、b、c、d}、3] は、{a、a、b}と{b、a、a}のような2つの要素を含むリストを返します。 同じ。

答えて

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

'Sort [#]&'は 'Sort'と同じです。 – dreeves

+0

@dreeves - d'oohhhh - それに応じて編集します。ありがとうございました。 –

+0

UnionをDeleteDuplicatesに置き換えてもよいが、与えられた優雅な方法に対しては利点がない。 (サブセットはKSubsetsに相当するMathematica 7です)。 Map/Sortを使わずに上記を行うことは可能ですか? – tomd

10

{na,nb,nc,nd}のように各組み合わせをエンコードすることができます。ここで、naは、aの番号が表示されます。次に、3までの4つの非負整数の可能な組み合わせをすべて見つけることです。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

+0

おそらくあまりにも複雑に見えますか? –

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] 

Edit-3

リストに繰り返し要素が含まれる場合、2つの方法が異なります。 からの出力、例えば、(または所望されなくてもよい)重複を含むであろう(アプローチ2)以下:

Select[Tuples[{a, b, c, d, a}, 3], OrderedQ] 
それらは容易に処分したことができる

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

ザ「真」と評価されたが、次の(1アプローチ(ハイパフォーマンスマーク法)によって生成されるリスト2に近づくために提示されたリストから重複要素を削除、および並べ替え:

lst = RandomInteger[9, 50]; 
Select[[email protected]@Tuples[lst, 3], OrderedQ] == 
[email protected][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]]] 

ごめんなさい!

+0

[#、OrderedQ]を選択すると、並べ替えることができなくなります。 –

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}} 
関連する問題