我在R中有以下代码(由Mark -Finding all possible combinations of numbers to reach a given sum发布),它允许我将数字加到目标值上。但是,我希望代码返回所有可能的组合,而不重复相同的数字,并将删除的数字存储在单独的列表中。我需要分配索引值吗?
x <- c(55,10,13,26,34,72,51,96,13)
subset_sum = function(numbers,target,partial=0){
if(any(is.na(partial))) return()
s = sum(partial)
if(s > target) return()
if(between(s,target-3,target)) print(sprintf("%s = %s",paste(partial[-1],collapse=" "),s))
for(i in seq_along(numbers)){
n = numbers[i]
remaining = numbers[(i+1):length(numbers)]
subset_sum(remaining,target,c(partial,n))
}
}
subset_sum(x,60)
#The actual output is:
[1] "10 13 34 = 57"
[1] "26 34 = 60"
#I expect the output as (no repetition of 34):
[1] 26 34 = 60
提前感谢!
发布于 2019-09-23 10:19:34
RcppAlgos
包(我是作者)就是专门为这个任务构建的。下面是一个利用comboGeneral
的解决方案,它用于生成有或没有重复以及多集的组合。我们还可以使用constraintFun
、comparisonFun
和limitConstraints
来约束输出
library(RcppAlgos)
mySubsetSum <- function(x, myTarget, repeats = FALSE) {
if (0 %in% x)
x <- x[-which(x == 0)]
if (repeats) {
tbl <- table(x)
vals <- as.numeric(names(tbl))
myfreqs <- unname(tbl)
} else {
vals <- unique(x)
myfreqs <- rep(1, length(vals))
}
## Add zero length(vals) - 1 times
myfreqs <- c(length(vals) - 1, myfreqs)
vals <- c(0L, vals)
combs <- comboGeneral(vals, length(vals), freqs = myfreqs,
constraintFun = "sum",
comparisonFun = "==",
limitConstraints = myTarget)
lapply(1:nrow(combs), function(x) combs[x, combs[x,] != 0])
}
mySubsetSum(x, 60)
[[1]]
[1] 26 34
mySubsetSum(x, 60, TRUE)
[[1]]
[1] 26 34
[[2]]
[1] 13 13 34
它是用C++
编写的,以获得最大的速度。以下是一个演示其效率的示例:
set.seed(42)
s <- sample(-50:50, 20)
s
[1] 42 43 -22 31 12 -1 19 -38 11 14 -9 41 33 -28 -10 30 38 -41 -11 -5
system.time(bigTest <- mySubsetSum(s, 170))
user system elapsed
0.039 0.000 0.040
length(bigTest)
[1] 2135
## Over 1 million total combinations
comboCount(c(0, s), 20, freqs = c(19, rep(1, 20)))
[1] 1048575
以下是bigTest
的输出示例
bigTest[1:5]
[[1]]
[1] -41 -38 -28 -22 -10 -5 11 12 14 19 30 31 33 38 41 42 43
[[2]]
[1] -41 -38 -28 -22 -9 -5 -1 11 12 14 19 30 31 33 38 41 42 43
[[3]]
[1] -41 -38 -28 -22 -1 11 12 19 30 31 33 38 41 42 43
[[4]]
[1] -41 -38 -28 -11 -10 -5 12 14 19 30 31 33 38 41 42 43
[[5]]
[1] -41 -38 -28 -11 -9 -5 -1 12 14 19 30 31 33 38 41 42 43
## View the last 5 combinations
bigTest[length(bigTest) - 4:0]
[[1]]
[1] 12 14 31 33 38 42
[[2]]
[1] 14 19 30 31 33 43
[[3]]
[1] 11 12 14 19 30 41 43
[[4]]
[1] 11 12 14 19 31 41 42
[[5]]
[1] 11 12 14 19 33 38 43
all(sapply(bigTest, sum) == 170)
[1] TRUE
您还可以查找在某个范围内具有和的组合。看起来OP最初是有这个想法的,因为OP使用了来自dplyr
的between
(至少我认为它来自dplyr
)。
sumRange <- comboGeneral(c(0, s), 20, freqs = c(19, rep(1, 20)),
constraintFun = "sum",
comparisonFun = c(">", "<"),
limitConstraints = c(155, 165))
all(rowSums(sumRange) > 155 & rowSums(sumRange) < 165)
[1] TRUE
https://stackoverflow.com/questions/57468130
复制相似问题