【问题标题】:How to find all the possible k integers which sum of them equals to a certain number in R如何找到所有可能的k个整数,它们的总和等于R中的某个数字
【发布时间】:2016-06-30 02:03:35
【问题描述】:

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

现在,我正在做的事情非常慢,我创建了从 1 到 n 的序列的 kth 笛卡尔积。然后遍历所有可能的组合以检查它是否满足总和。下面是我的代码。

先得到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)
}

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

然后循环

combine = cart(v=seq(1,n),k=k)
sum = 0
for(i in 1:dim(combine)[1]){
  if(sum(combine[i,])==n){
    sum = sum + sum(combine[i,])
  }
}

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

【问题讨论】:

    标签: r algorithm


    【解决方案1】:

    根据对 cme​​ts 中问题的澄清进行编辑:

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

    要获取组合,请使用 partitions 包中的 compositions() 函数:

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

    原始答案,在包作者​​有机会看到之前保留:

    如果我正确理解您的问题,您可以使用 partitions 包中的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
    

    【讨论】:

    • 谢谢,乔希,但我在实施限制部分(4,3,include.zero = F)时出错,谢谢
    • @weikangduan 不错的收获。这是由于restrictedparts() 中的一个错误。请参阅我的编辑以获得简单的解决方法。
    • 嗨@Josh,谢谢。但是我要找的结果是 1 1 2、1 2 1 和 2 2 1。有没有办法解决这个问题?谢谢。
    • @weikangduan 那些叫作曲,你可以通过partitions::compositions(4, 3, include.zero=FALSE)得到,
    【解决方案2】:

    这是使用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,并且在OP的问题中定义了k和n。

    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
    

    【讨论】:

    • 为什么将x 限制为小于1:(n-k+1) 的任何内容?
    • 我在 combn(x, k, FUN = sum, simple = TRUE) 中遇到错误:'FUN' 必须是函数或 NULL,我想知道哪里出错了,谢谢跨度>
    • @CarlWitthoft 对不起。哪个部分限制了 x?我认为该函数在技术上将采用任何向量(尽管仅适用于整数)。
    • @weikangduan 尝试复制并粘贴我的答案。我刚刚在新的 R 会话中尝试了这两个版本,它们都有效。
    • 我只是想我们会想要所有可能的 :-) 。顺便说一句,您不需要 whichR 将对逻辑向量进行操作。
    猜你喜欢
    • 1970-01-01
    • 2014-09-26
    • 2014-10-17
    • 2018-07-31
    • 1970-01-01
    • 2014-11-07
    • 1970-01-01
    • 2019-12-17
    • 1970-01-01
    相关资源
    最近更新 更多