假设我有一个整数n
和k
,我需要找到总计为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)
}
这超级慢,我想知道有没有更快的方法来实现它?
答案 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