如何找到所有可能的k个整数,它们的总和等于R中的某个数字

时间:2016-06-28 16:32:31

标签: r algorithm

假设我有一个整数nk,我需要找到总计为k的{​​{1}}整数的所有可能组合。我想知道如何有效地实现这一点。

现在,我正在做的事情是超级慢,我创建了从{1到n'的序列的n笛卡尔积。然后遍历所有可能的组合以检查它是否满足sum.Below是我的代码。

首先获得k笛卡儿产品

kth

v是从1到n的序列,k是整数

然后循环

cart = function(v,k){
  x = v
  f = v
  for(i in 1:(k-1)){
    f = merge(f,x,all=T)
    f = as.matrix(f)
    colnames(f) = NULL
  }
  return(f)
}

这超级慢,我想知道有没有更快的方法来实现它?

2 个答案:

答案 0 :(得分:5)

根据评论中的问题说明进行编辑:

听起来你想要所有的合成,而不是整数n的所有分区。 (两个序列仅按其术语顺序不同被认为是相同的分区,但不同的组合。)

要获取合成,请使用分区包中的compositions()功能:

library(partitions)
compositions(4, 3, include.zero=FALSE)
#           
# [1,] 2 1 1
# [2,] 1 2 1
# [3,] 1 1 2

原始回答,在包裹作者有机会看到它之前保留原样:

如果我正确理解了您的问题,您可以使用分区包中的restrictedparts()

例如:

library(partitions)

restrictedparts(9,4)
#                                         
# [1,] 9 8 7 6 5 7 6 5 4 5 4 3 6 5 4 4 3 3
# [2,] 0 1 2 3 4 1 2 3 4 2 3 3 1 2 3 2 3 2
# [3,] 0 0 0 0 0 1 1 1 1 2 2 3 1 1 1 2 2 2
# [4,] 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 2

## Or, for partitions employing only non-zero integers
restrictedparts(9,4,include.zero=FALSE)
#                 
# [1,] 6 5 4 4 3 3
# [2,] 1 2 3 2 3 2
# [3,] 1 1 1 2 2 2
# [4,] 1 1 1 1 1 2

由于restrictedparts的倒数第二行中存在小错误,当给定限制只允许一个分区时,它可能会抛出错误。我已经向包作者发送了一个建议的修复程序,但在此期间你可以通过设置函数参数decreasing=FALSE来解决这个问题:

## Throws an error
restrictedparts(4,3,include.zero=FALSE)
# Error in class(x) <- "matrix" : 
# invalid to set the class to matrix unless the dimension attribute is of # length 2 (was 0)

## Works just fine
restrictedparts(4,3,include.zero=FALSE,decreasing=FALSE)
#       
# [1,] 1
# [2,] 1
# [3,] 2

答案 1 :(得分:4)

这是使用combn的基本R方法。假设您有1到12的整数,并且您希望找到所有5个数字的总和为20的数组。

myGroups <- combn(1:12, 5)
mysums <- combn(1:12, 5, FUN=sum, simplify=TRUE)

myAnswers <- myGroups[, mysums == 20]

这将返回一个矩阵,其中列是数字集:

myAnswers
     [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,]    1    1    1    1    1    1    2
[2,]    2    2    2    2    2    3    3
[3,]    3    3    3    4    4    4    4
[4,]    4    5    6    5    6    5    5
[5,]   10    9    8    8    7    7    6

这很容易包含在一个函数中。在下面的函数中,x是输入向量,我在上面的例子中设置为1:12,k和n在OP的问题中定义。

myfunction <- function(x, k, n) {
  myGroups <- combn(x, k)
  mysums <- combn(x, k, FUN=sum, simplify=TRUE)

  myGroups[, mysums == n]
}

注意
此方法假定x中的每个条目将在计算中使用一次,因此在使用其中4个加起来为9的整数0:9中,myfunction返回:

myfunction(0:9, 4, 9)
     [,1] [,2] [,3]
[1,]    0    0    0
[2,]    1    1    2
[3,]    2    3    3
[4,]    6    5    4

注意
如果目标是允许重复使用这些整数,我们只需调整我们提供给myfunction的内容。请注意,这将导致集合的重复输出,因为顺序对combn很重要。

如果涉及重复的整数,则必须修改combn的使用以返回列表,以便我们可以使用unique删除重复的集合:

myfunctionDupes <- function(x, k, n) {
  # return list instead of matrix, with elements sorted
  myGroups <- lapply(combn(x, k, simplify=FALSE), sort)
  # find duplicates
  dupes <- duplicated(myGroups)
  # subset summations to those where myGroups is not a duplicate
  mysums <- combn(x, k, FUN=sum, simplify=TRUE)[!dupes]
  # subset myGroups to the unique values then those with sums == n
  myGroups <- (myGroups[!dupes])[mysums == n]
  # return a matrix
  do.call(cbind, myGroups)
}

这需要一些时间来运行@ josh-obrien的例子,但它会产生相同的结果:

myfunctionDupes(rep(0:9, 4), 4, 9)
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14] [,15] [,16] [,17] [,18]
[1,]    0    0    0    0    0    0    0    0    0     0     0     0     1     1     1     1     1     2
[2,]    1    1    1    1    0    2    2    0    0     3     0     0     2     2     1     1     1     2
[3,]    2    3    4    1    1    3    2    2    3     3     4     0     3     2     2     3     1     2
[4,]    6    5    4    7    8    4    5    7    6     3     5     9     3     4     5     4     6     3