我有以下一组数字10、17、5、7、15。从这些数字中,我需要找到总和小于或等于35的所有3个数字组合。在一个这样的组合中,特定数字不应包含多个。 例如:10,10,5是错误的组合,因为10重复了两次。
我尝试了这段代码,但没有给出我所需要的。
import { BreakpointObserver, Breakpoints, BreakpointState } from '@angular/cdk/layout';
import { Component, OnInit } from '@angular/core'
@Component({
selector: 'navbar',
templateUrl: './navbar.component.html',
styleUrls: ['./navbar.component.css']
})
export class NavbarComponent implements OnInit {
htmlStyles: string;
constructor(private breakpointObserver: BreakpointObserver) { }
ngOnInit() {
this.breakpointObserver.observe([Breakpoints.Small])
.subscribe((state: BreakpointState) => {
if (state.matches) {
this.htmlStyles = 'dummy1';
} else {
this.htmlStyles = 'dummy2';
}
});
}
}
上述代码输出的一部分如下,
library(data.table)
df=expand.grid(x1=c(10,17,5,7,15),
x2=c(10,17,5,7,15),
x3=c(10,17,5,7,15)
)
setDT(df)
df[(x1+x2+x3) <= 35]
根据上述输出,可以观察到一个数字出现多次。 有人可以提示获得预期结果的提示吗?
谢谢
答案 0 :(得分:6)
请尝试以下操作,看看问题是否出在此。
x <- c(10,17,5,7,15)
i <- combn(x, 3, sum) <= 35
combn(x, 3)[, i]
# [,1] [,2] [,3] [,4] [,5] [,6] [,7]
#[1,] 10 10 10 10 10 17 5
#[2,] 17 17 5 5 7 5 7
#[3,] 5 7 7 15 15 7 15
以上是一般想法。下面f2
是一种更有效的内存和速度实现方式。
f1 <- function(x, n = 3, thres = 35){
i <- combn(x, n, sum) <= thres
combn(x, n)[, i]
}
f2 <- function(x, n = 3, thres = 35){
cmb <- combn(x, n)
cmb[, colSums(cmb) <= thres]
}
检查结果是否全部具有不同的数字。
res <- f2(x)
apply(res, 2, function(y){
all(y[-1] != y[1])
})
#[1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE
identical(f1(x), f2(x))
#[1] TRUE
现在是时间功能了。
microbenchmark::microbenchmark(f1 = f1(x),
f2 = f2(x))
#Unit: microseconds
# expr min lq mean median uq max neval cld
# f1 105.150 107.383 110.66616 108.6535 109.896 238.899 100 b
# f2 62.779 65.568 67.65754 66.4290 67.145 122.119 100 a
答案 1 :(得分:5)
软件包comboGeneral
(我是作者)中的函数RcppAlgos
是专门为此任务设计的。
library(RcppAlgos)
x <- c(10,17,5,7,15)
comboGeneral(x, 3,
constraintFun = "sum",
comparisonFun = "<=",
limitConstraints = 35)
[,1] [,2] [,3]
[1,] 5 7 10
[2,] 5 7 15
[3,] 5 7 17
[4,] 5 10 15
[5,] 5 10 17
[6,] 7 10 15
[7,] 7 10 17
这也是非常有效的。观察:
set.seed(42)
s <- sample(100, 25)
s
[1] 92 93 29 81 62 50 70 13 61 65 42 91 83 23 40 80 88 10 39 46 73 11 78 85 7
system.time(a <- comboGeneral(s, 10,
constraintFun = "sum",
comparisonFun = "<=",
limitConstraints = 600))
user system elapsed
0.232 0.046 0.278
dim(a)
[1] 2252362 10
与@RuiBarradas发布的更高效的函数f2
和@Cole发布的dt_checker
相比:
system.time(b <- f2(s, 10, 600))
user system elapsed
3.283 0.093 3.418
system.time(a2 <- dt_checker(s, 10, 600))
user system elapsed
1.803 0.319 0.646
还应该注意,comboGeneral
之后的算法会在获得解决方案后立即终止。因此,在不同的约束条件下,时序会有所不同。观察:
system.time(a <- comboGeneral(s, 10,
constraintFun = "sum",
comparisonFun = "<=",
limitConstraints = 400))
user system elapsed
0.003 0.001 0.003
但是,在其他解决方案中,必须先创建所有组合然后进行过滤(这不会花很长时间),因此时序与之前相似。
system.time(b <- f2(s, 10, 400))
user system elapsed
2.933 0.039 2.973
system.time(a2 <- dt_checker(s, 10, 400))
user system elapsed
1.786 0.276 0.627
作为最终基准,我们对所有约束条件下的所有结果进行基准测试:
system.time(a <- lapply(seq(200, 600, 25), function(x) {
t <- comboGeneral(s, 10,
constraintFun = "sum",
comparisonFun = "<=",
limitConstraints = x)
dim(t)
}))
user system elapsed
0.498 0.125 0.623
system.time(a2 <- lapply(seq(200, 600, 25), function(x) {
t <- dt_checker(s, 10, x)
dim(t)
}))
user system elapsed
34.448 4.633 10.693
identical(a, a2)
[1] TRUE
答案 2 :(得分:4)
我们可以删除值为any
duplicated
的行,然后选择总和为<= 35
的行
df1 <- df[!apply(df, 1, function(x) any(duplicated(x))), ]
df1[rowSums(df1) <= 35, ]
# x1 x2 x3
#8 5 17 10
#9 7 17 10
#12 17 8 10
#13 5 8 10
#14 7 8 10
OP代码中的原始df
具有c(10,17,5,7,15)
的所有可能组合,并且有很多重复。使用apply
循环,我们删除所有重复值的行。因此具有10、10的行将被删除,而具有17、17和其他重复的行将被删除。 df1
是没有重复数字的数据框。现在,我们仅对总和小于35的那些行进行子集化。
答案 3 :(得分:4)
您可能不想在更多列上执行此操作,但这很简单:
df[(x1+x2+x3) <= 35 & x1 != x2 & x2 != x3 & x3 != x1]
如果您认为10,17,5与5,10,17相同,因此只需保留一次,则:
df[(x1+x2+x3) <= 35 & x1 < x2 & x2 < x3]
答案 4 :(得分:3)
这里的答案取决于def appcompat_version = "1.1.0-rc01"
def material_version = "1.1.0-alpha09"
// Java
implementation "androidx.appcompat:appcompat:$appcompat_version"
implementation "com.google.android.material:material:$material_version"
的非等额联接。大部分时间都花在操纵字符向量上,以便在data.table
调用中求值。
dt
我主要是这样做的,以了解我能否比library(data.table)
dt_checker <- function(y, n, criteria) {
x_dt <- data.table(x1 = y)
setkey(x_dt, x1)
x_res <- copy(x_dt)[seq_len(length(y)-(n-1))]
for (i in seq_len(n)[-1]) {
setnames(x_dt, paste0('x', i))
cols <- paste0('x', seq_len(i))
cols2 <- cols
cols2[i-1] <- paste0('x.', cols2[i-1])
x_res <- x_res[x_dt, on = paste(cols[c(i-1, i)], collapse = '<'), ..cols2, allow.cartesian = T, nomatch = 0L]
setnames(x_res, cols)
}
x_res[x_res[, rowSums(.SD)<= criteria] ,]
}
dt_checker(x, 3, 35)
x1 x2 x3
1: 5 7 10
2: 5 7 15
3: 5 10 15
4: 7 10 15
5: 5 7 17
6: 5 10 17
7: 7 10 17
解决方案更快地得到data.table
。我不能,在花时间使所有这些连接自动化的逻辑上,我大概可以在RcppAlgos
中找到它:)。
Rcpp
此外,对于较小的数据集,这也将起作用。但是对于较小的数据集,@ Rui的解决方案几乎与system.time(a <- comboGeneral(s, 10,
+ constraintFun = "sum",
+ comparisonFun = "<=",
+ limitConstraints = 600))
user system elapsed
0.10 0.13 0.23
system.time(a2 <- dt_checker(s, 10, 600))
user system elapsed
0.54 0.09 0.57
system.time(a3 <- f2(s, 10, 600))
user system elapsed
3.98 0.00 4.01
一样快,并且是基本解决方案。
RcppAlgos