与重复的组合

发布于 2024-10-05 10:53:40 字数 470 浏览 7 评论 0原文

我正在使用 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}...等元素。

它可能需要自定义功能。如果我能想出一个答案,我会发布答案,但目前我没有看到明显的解决方案。

编辑: 理想情况下,输出不会包含重复的组合,例如 元组[{a, b, c, d}, 3] 将返回一个包含两个元素的列表,例如 {a,a,b} 和 {b,a,a} 从组合的角度来看,它们是相同的。

I'm using Mathematica 7 and with a combinatorica package function I can get all combinations of a certain number from a list of elements where the order doesn't matter and there is no repetition.e.g:

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

I cannot find a function that will give me all combinations of a certain number from a list of elements where the order doesn't matter and there is repetition.
i.e. the above example would include elements like {a,a,b},{a,a,a},{b,b,b}...etc in the output.

It may require a custom function. If I can come up with one I will post an answer but for now I don't see an obvious solution.

Edit:
Ideally the output will not contain duplication of a combination e.g.
Tuples[{a, b, c, d}, 3]
will return a list that contains two elements like {a,a,b} and {b,a,a}
which from a combinations point of view are the same.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

删除会话 2024-10-12 10:53:40

您可以将每个组合编码为 {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 和 Tuple 之间的时间比较(以日志秒为单位)

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]


(来源:yaroslavvb.com

You can encode each combination as {na,nb,nc,nd} where na gives the number of times a appears. The task is then to find all possible combinations of 4 non-negative integers that add up to 3. IntegerPartition gives a fast way to generate all such such combinations where order doesn't matter, and you follow it with Permutations to account for different orders

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]

Just for fun, here's timing comparison between IntegerPartitions and Tuples for this task, in log-seconds

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]


(source: yaroslavvb.com)

美煞众生 2024-10-12 10:53:40
DeleteDuplicates[Map[Sort, Tuples[{a, b, c, d}, 3]]]
DeleteDuplicates[Map[Sort, Tuples[{a, b, c, d}, 3]]]
软的没边 2024-10-12 10:53:40

这是一个简单的解决方案,它利用 Mathematica 的内置函数 Subsets,因此在简单性和性能之间取得了很好的平衡。 [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}}

Here's a simple solution that takes advantage of Mathetmatica's built-in function Subsets and thus is a nice balance between simplicity and performance. There is a simple bijection between k-subsets of [n+k-1] and k-combinations of [n] with repetition. This function changes subsets into combinations with repetition.

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

So

CombWithRep[4,2]

yields

{{1,1},{1,2},{1,3},{1,4},{2,2},{2,3},{2,4},{3,3},{3,4},{4,4}}
以酷 2024-10-12 10:53:40

High Performance Mark 给出的优雅方法的一个细微变化:

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

排列稍微更通用(但不是您正在寻找的?)

例如:

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

给出以下

alt text

编辑:

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

可能更好

Edit-2

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

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

编辑3。

如果列表包含重复元素,这两种方法将会有所不同。输出来自
例如,以下(方法 2)将包含重复项(可能需要也可能不需要):

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

它们可以很容易地被删除:

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

以下计算结果为“True”(从提供给方法 2 的列表中删除重复元素,并对方法 1(高性能标记方法)生成的列表进行排序:

lst = RandomInteger[9, 50]; 
Select[Union@Sort@Tuples[lst, 3], OrderedQ] == 
 Sort@DeleteDuplicates[Map[Sort, Tuples[lst, 3]]]

如下所示(从方法 2 的输出中删除重复项,对方法 1 的输出进行排序):

lst = RandomInteger[9, 50]; 
Union@Select[Sort@Tuples[lst, 3], OrderedQ] == 
 Sort@DeleteDuplicates[Map[Sort, Tuples[lst, 3]]]

对此感到抱歉!

A slight variant on the elegant method given by High Performance Mark:

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

Permutations is slightly more versatile (but not what you are looking for?)

For example:

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

gives the following

alt text

Edit:

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

is probably better

Edit-2

Of course, Cases may also be used. For example

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

Edit-3.

The two approaches will differ if the list contains a repeated element. The output from
the following (approach 2), for example, will contain duplicates (which may or may not be desired):

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

They may easily be got rid of:

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

The following evaluates to 'True' (remove duplicate elements from the list presented to approach 2, and Sort the list produced by approach 1 (High Performance Mark method):

lst = RandomInteger[9, 50]; 
Select[Union@Sort@Tuples[lst, 3], OrderedQ] == 
 Sort@DeleteDuplicates[Map[Sort, Tuples[lst, 3]]]

as does the following (remove duplicates from output of approach 2, Sort output of approach 1):

lst = RandomInteger[9, 50]; 
Union@Select[Sort@Tuples[lst, 3], OrderedQ] == 
 Sort@DeleteDuplicates[Map[Sort, Tuples[lst, 3]]]

Sorry about that!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文