r - 如何找出总和最接近给定数字的给定向量的最佳组合



我的问题与此非常相似:从一组整数中查找一个子集,其总和最接近一个值

它只讨论了算法,但我想用 R 解决它。我对R很陌生,并试图制定解决方案,但我想知道是否有更有效的方法。

这是我的例子:

# Define a vector, to findout a subset whose sum is closest to the reference number 20. 
A <- c(2,5,6,3,7)
# display all the possible combinations
y1 <- combn(A,1)
y2 <- combn(A,2)
y3 <- combn(A,3)
y4 <- combn(A,4)
y5 <- combn(A,5)
Y <- list(y1,y2,y3,y4,y5)
# calculate the distance to the reference number of each combination
s1 <- abs(apply(y1,2,sum)-20)
s2 <- abs(apply(y2,2,sum)-20)
s3 <- abs(apply(y3,2,sum)-20)
s4 <- abs(apply(y4,2,sum)-20)
s5 <- abs(apply(y5,2,sum)-20)
S <- list(s1,s2,s3,s4,s5)
# find the minimum difference
M <- sapply(S,FUN=function(x) list(which.min(x),min(x)))
Mm <- which.min(as.numeric(M[2,]))
# return the right combination
data.frame(Y[Mm])[as.numeric(M[,Mm[1]])]

所以答案是2,5,6,7。

如何优化此程序?尤其是五个 combn() 和五个 apply(),有没有一种方法可以同时处理它们?我希望当 A 中有更多项目时,我可以使用 length(A) 来覆盖它。

这是另一种方法,

l1 <- sapply(seq_along(A), function(i) combn(A, i))
l2 <- sapply(l1, function(i) abs(colSums(i) - 20))
Filter(length, Map(function(x, y)x[,y], l1, sapply(l2, function(i) i == Reduce(min, l2))))
#[[1]]
#[1] 2 5 6 7

最后一行使用Map根据通过从列表l2中查找最小值而创建的逻辑列表为l1编制索引。

combiterisubsetv迭代器,它遍历向量的所有子集。 与foreach相结合可简化代码。

library(combiter)
library(foreach)
A <- c(2,5,6,3,7)
res <- foreach(x = isubsetv(A), .combine = c) %do% sum(x)
absdif <- abs(res-20)
ind <- which(absdif==min(absdif))
as.list(isubsetv(A))[ind]

最新更新