【发布时间】:2017-08-29 16:17:05
【问题描述】:
一位朋友向我提出了一个编程问题,关于如何确定一组值的所有可能组合可以相加以获得所需的总数。我有一个解决方案,但它不够优雅(它基本上只是一系列 for 循环和 if 语句)。我确信 dplyr 有一个我想不出的解决方案,因为我知道它有多么有用,但我还没有很擅长它。我将在下面发布问题和我的脚本。
问题: 有一个目标,上面有六个环,每个环的价值不同。这些值是 1、2、3、4、5 或 6。您可以使用多少种不同的环组合来获得正好 9 分?
所以要考虑: 顺序不重要 您可以根据需要使用尽可能少或尽可能多的值 您可以多次获得相同的值(因此 9 1 是一个完全有效的选项)
我曾考虑首先使用 combinat 包中的 combn(),但 combn() 不会替换值。
然后我决定使用一系列嵌套的 for 循环和 if 语句(我将其截断为您最多只能使用 6 个值,因为虽然我可能有空闲时间,但我不是一个即将编写一个允许最多 9 个值的循环)。所以本质上,它运行了 6 个可能值的 for 循环。当我只需要 2 个值而不是 6 时,我将数字 0 包含到可能值列表中表示不尝试(因此 4+5+0+0+0+0 是此循环中的有效输出,但它不会能够做 4+5,因为它总是会尝试添加更多的非零值)。
## Create a vector x with possible values
x = c(1,2,3,4,5,6)
## Add in value 0 because I need to be able to write this dumb loop that allows many terms to be used, but also allows smaller amounts of terms to be used
x = c(x,0);x
## Creating empty data.frame to input solutions to so that I can check for uniqueness of solution
df = data.frame("a" = as.numeric(),
"b" = as.numeric(),
"c" = as.numeric(),
"d" = as.numeric(),
"e" = as.numeric(),
"f" = as.numeric())
for (a in x){
for (b in x){
for (c in x){
for (d in x){
for (e in x){
for (f in x){
m = sum(a,b,c,d,e,f)
if(m == 9) {
p = 0
n = c(a,b,c,d,e,f)
if (nrow(df) == 0){
df[1,] = n
}
if (nrow(df) >= 1){
for (i in (1:nrow(df))){
if(setequal(n,df[i,]) == TRUE){
p = p+1
}}
if(p == 0){
df = rbind(df,n)
}
}
}
}
}
}
}
}
}
## Convert any 0 values to NA
df[df==0] = NA
## Check Solutions
df
我创建了一个空的 data.frame 来存储解决方案,然后在循环中,我创建了一个测试,以查看循环中的新解决方案是否与先前找到的值的组合匹配,如果是,它不会 rbind( ) 到 data.frame。
我确信有一种更好的方法可以做到这一点,它允许动态最大数量的值(因此在这种情况下可以软编码将每个解决方案中的最大值数量更改为 9 而不是我的硬编码 6,或者如果我想要的总数是 5 而不是 9,则将其降为 5)。如果您有任何建议可以减少这种笨重、充满循环的混乱,我们将不胜感激!
【问题讨论】:
-
例如
library(partitions);p <- parts(9);p[ , colSums(p > 6) == 0].
标签: r for-loop combinations