【问题标题】:Listing all integer compositions in R列出 R 中的所有整数组合
【发布时间】:2020-10-08 12:45:36
【问题描述】:

我寻找的基本上是这个问题答案的 R 版本:Generating all permutation of numbers that sums up to N。首先,答案使用 java,我很难阅读。其次,代码使用“双端队列”,我想不出在 R 中实现的方法。 我找到了几种算法来做到这一点,但它们都是用编程语言编写的,使用 R 中不可用的结构,例如双端队列、堆或列表理解。

我真正需要的是找到长度为 N-1 的所有向量 v 的方法,其中: sum(v * 1:(N-1)) == N 而且我认为只要我找到一种获取所有有序整数分区的方法,我自己就可以做到这一点。

以 N = 4 为例,所有使用数字 1 到 N-1 的有序整数分区是:

1+1+1+1

1+1+2

1+3

2+2

我实际上需要的是两种形式的输出:

c(1,1,1,1)

c(1,1,2)

c(1,3)

c(2,2)

或形式:

c(4,0,0)

c(2,1,0)

c(1,0,1)

c(0,2,0)

因为我应该能够自己将前一种格式转换为后一种格式。任何有关如何使用 R 解决此问题的提示将不胜感激。后一种格式恰好是向量v,使得sum(v * 1:3) 为4。

编辑: 我自己的尝试:

rek = function(mat, id1, id2){
  if(id1 + id2 != length(mat) + 1){ #If next state not absorbing
    mat[id1] = mat[id1] - 1
    mat[id2] = mat[id2] - 1
    mat[id1+id2] = mat[id1+id2] + 1
    out = mat
    
    id = which(mat > 0)
    for(i in id){
      for(j in id[id>=i]){
        if(j == i & mat[i] == 1){
          next
        }
        out = rbind(out, rek(mat,i,j))
      }
    }
    return(out)
  }
}
start = c(n, rep(0, n-2))
states = rbind(start, rek(start, 1, 1))
states = states[!duplicated(states), ] #only unique states.

这是非常低效的。例如。当n = 11 时,我的states 在删除重复项之前有超过 120,000 行,只剩下 55 行。

编辑 2: 使用下面描述的parts() 函数我想出了:

temp = partitions::parts(n)
temp = t(temp)
for(i in 1:length(temp[,1])){
  row = temp[i,]
  if(any(row>(n-1))){#if absorbing state
    next
  }
  counts = plyr::count(row[row>0])
  newrow = rep(0,n-1)
  id = counts$x
  numbs = counts$freq
  newrow[id] = numbs
  states = rbind(states, newrow)
}
states = states[-1,]#removing the first row, added manually

这恰好给了我向量v,使得sum(v * 1:(N-1)) 是N。

如果有人感兴趣,这将在合并理论中使用,作为描述 N 个个体之间可能的关系的一种方式,当所有人都相关时省略。以 N = 4 为例:

(4, 0, 0) -- 没有个人相关

(2, 1, 0) -- 两个人有关系,其他人没有关系

(0, 2, 0) -- 个体是成对相关的

(1, 0, 1) -- 三个人有关系,另一个人没有关系。

【问题讨论】:

  • 你需要用这个解决的真正问题有多大?
  • 我希望可以为非常大的 N 做,但我认为有一个限制。我实际上想出了一个非常低效的方法,它在 N = 13 左右“死亡”。为此,我发现排列是:N=2:1,N=3:2,N=4:4,N= 5:6,N=6:10,N=7:14,N=8:21,N=9:29,N=10:41,N=11:55,N=12:76 但是,我是不是 100% 确定它是正确的,因为我没有费心检查我是否得到了所有东西,因为算法太慢了。
  • 对于更复杂的数据结构我推荐cran.r-project.org/web/packages/collections/index.html
  • @polkas 谢谢。这在我未来的功能中也将非常有用。

标签: r


【解决方案1】:

希望包裹partitions中的parts能提供帮助

library(partitions)
N <- 4
res <- unique(lapply(asplit(parts(N),2),function(x) sort(x[x>0])))[-1]

给了

> res
[[1]]
[1] 1 3

[[2]]
[1] 2 2

[[3]]
[1] 1 1 2

[[4]]
[1] 1 1 1 1

如果您想编写自定义 base R 函数,这里是递归版本

f <- function(n, vhead = n, v = c()) {
  if (n == 0) return(list(v))
  unlist(lapply(seq_len(min(n, vhead)), function(k) f(n - k, k, c(k,v))), recursive = FALSE)
}

然后我们可以运行

res <- Filter(function(x) length(x)>1,f(N))

【讨论】:

  • 感谢您的回答。 parts() 非常有用,既可以以您的答案形式回答我的实际问题,也可以包含在其他功能中。但只是写t(parts(N)) 的格式实际上很容易满足我的基本需求。在提出问题之前,我不明白在我的谷歌搜索期间图书馆没有出现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多