【问题标题】:Generating all permutations of N balls in M bins在 M 个 bin 中生成 N 个球的所有排列
【发布时间】:2014-11-21 15:23:27
【问题描述】:

我想在m 箱中生成一组n 球的排列。下面的一组嵌套列表会生成这些排列。

n <- 3
m <- 4
v <- rep(0,m)
for (i in n:0){
  for (j in (n-sum(i)):0){
    for (k in (n-sum(i,j)):0){
      for (l in (n - sum(i,j,k)):0){
        v <- c(i,j,k,l)
        print(v)
        if (sum(v) == n){ break }
      }
    }
  }
}

打印解决方案:

[1] 3 0 0 0
[1] 2 1 0 0
[1] 2 0 1 0
[1] 2 0 0 1
[1] 1 2 0 0
[1] 1 1 1 0
[1] 1 1 0 1
[1] 1 0 2 0
[1] 1 0 1 1
[1] 1 0 0 2
[1] 0 3 0 0
[1] 0 2 1 0
[1] 0 2 0 1
[1] 0 1 2 0
[1] 0 1 1 1
[1] 0 1 0 2
[1] 0 0 3 0
[1] 0 0 2 1
[1] 0 0 1 2
[1] 0 0 0 3

排列的总数将是choose(n+m-1,m-1),排列的顺序对我来说并不重要。但是我很难把它变成一个可以接受任意数量的垃圾箱的函数。 (我不会用我的尝试破坏井,不过它只是嵌套循环的混乱。)因此,如果有人比我更精明,可以将上面的嵌套循环转换为函数,我将不胜感激。

或者,如果已经有一个函数可用于执行这种类型的排列(或要遵循的不同算法),我将不胜感激。我更喜欢一种不会产生多余排列的方法(这里加起来不等于n)然后丢弃它们,但对于像这样的小问题,这样做的解决方案是可以接受的。

【问题讨论】:

  • 一种方法,当然不是最有效但比多个嵌套 for 循环更好,是:x &lt;- expand.grid(rep(list(0:n), m)); x[rowSums(x) == n,]
  • 谢谢@beginneR!我在使用 expand.grid 时遇到了我想要的问题,不过这个例子对我来说有点清楚。
  • 永远不要永远重新发明一个明显的轮子。各种包装中有大量类似梳子和烫发的工具。 (例如乔希的回答)
  • 不确定投反对票的意义何在。在我创建这个问题之前,我当然调查了几个包,例如combinationspermutations 加上基本的 R 函数。
  • 如果您还没有看过它,您可能会发现this question and answer 作为一般参考很有用。它并不全面,但确实指出了 R 中许多有用的组合包。

标签: r permutation


【解决方案1】:
library(partitions)
compositions(3,4)

# [1,] 3 2 1 0 2 1 0 1 0 0 2 1 0 1 0 0 1 0 0 0
# [2,] 0 1 2 3 0 1 2 0 1 0 0 1 2 0 1 0 0 1 0 0
# [3,] 0 0 0 0 1 1 1 2 2 3 0 0 0 1 1 2 0 0 1 0
# [4,] 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 2 2 2 3

【讨论】:

  • 谢谢,partitions 库从未出现在我的搜索尝试中。查看源代码,我也永远不会想出那个解决方案。
【解决方案2】:

以下通过使用更通用的包iterpc给出了一个略有不同但等效的答案

m = 4; n = 3
library(iterpc)
I = iterpc(m, n, replace=T)
getall(I)

输出是 n 个球的箱号。

     [,1] [,2] [,3]
 [1,]    1    1    1
 [2,]    1    1    2
....
....
[18,]    3    3    4
[19,]    3    4    4
[20,]    4    4    4

第一行表示3个球都来自bin 1,最后一行表示3个球都来自bin 4。

您可以通过计算 1、2、3 和 4 的数字来轻松产生所需的结果。也可以利用迭代器依次生成结果。

count <- function(x){
    as.numeric(table(factor(x, levels=1:m)))
}
I = iterpc(m, n, replace=T)


> count(getnext(I))
[1] 3 0 0 0
> count(getnext(I))
[1] 2 1 0 0
> count(getnext(I))
[1] 2 0 1 0
> count(getnext(I))
[1] 2 0 0 1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-09
    • 1970-01-01
    • 1970-01-01
    • 2020-08-14
    • 1970-01-01
    • 2011-05-08
    相关资源
    最近更新 更多