下面是交换函数,它交换列表中小于10的值
swapFun <- function(x, n = 10){
inx <- which(x < n)
x[sample(inx)] <- x[inx]
x
}
例如,原始列表是1、2、3、10、4、11。
通过采样交换后,此列表可能是2、1、4、10、3、11或1、3、2、10、4、11。
但是我想将每个小于10的值交换为小于10的另一个值。
例如,第一个结果(即2、1、4、10、3、11)是我想要的,因为每个小于10的值都已交换为小于10的另一个值。
但是第二个结果(即1、3、2、10、4、11)不是我想要的,因为1和4尚未交换为小于10的其他值。
如果没有可行的解决方案,只需打印“没有可行的解决方案”
有什么建议吗? 非常感谢。
答案 0 :(得分:6)
您正在寻找小于10的值derangement。根据排列理论,随机选择的排列中大约有1 / e(37%)是排列,因此命中或未命中方法是合理的,有一个重要的警告。
小于n
的项目之间可能存在重复。并非所有这些项目的排列都是可区分的,因此并非所有项目的排列都看起来像排列:彼此交换两个2(例如)在某种意义上是排列,但看起来并不像排列。 1/e
启发式方法适用于头寸的原始排列,不适用于值的可区分排列。如果重复次数很高,则可能需要的时间比建议的1 / e长。如果在用例中性能不令人满意,则需要用更复杂的函数(可以随机选择可区分的排列)替换函数定义中的sample()
。
就可行性而言,只要小于n
的最常见元素在小于n
的项中所占的比重不超过50%,就会有可行的解决方案>
derangement <- function(x){
if(max(table(x)) > length(x)/2) return(NA)
while(TRUE){
y <- sample(x)
if(all(y != x)) return(y)
}
}
swapFun <- function(x, n = 10){
inx <- which(x < n)
y <- derangement(x[inx])
if(length(y) == 1) return(NA)
x[inx] <- y
x
}
例如,
> set.seed(10)
> swapFun(c(1,2,10,4,11,2,12))
[1] 2 4 10 2 11 1 12
> swapFun(c(2,2,10,4,11,2,12))
[1] NA
请注意,没有有效的排列长度为1,但是NA
的长度为1,因此测试y
的长度是测试是否可以对值进行排列的有效方法。如果不存在小于n的值的排列,则函数返回NA
。您可以根据需要测试NA并打印“没有可行的解决方案”
答案 1 :(得分:1)
此功能为您提供数字
require(combinat)
x <- c(1,2,10,4,11,2,12)
m <- 10
swapFun <- function(x, m){
# determine positions of values to be permutated or fixed
xi <- which(x < m)
xj <- which(x >= m)
# make permuations
xp <- do.call(rbind, permn(x[xi]))
# make matrix with permutated and fixed values
xn <- matrix(nrow = nrow(xp), ncol = length(x))
xn[ ,xi] <- xp
xn[ ,xj] <- sort(rep(x[xj],nrow(xp)))
# delete duplicates
d <- !duplicated(apply(xn, 1, paste, collapse = "_"))
xn <- xn[d,]
return(xn)
}
swapFun(x,m)
> swapFun(x,m)
[,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,] 1 2 10 4 11 2 12
[2,] 1 2 10 2 11 4 12
[3,] 2 1 10 2 11 4 12
[4,] 2 1 10 4 11 2 12
[5,] 1 4 10 2 11 2 12
[6,] 4 1 10 2 11 2 12
[7,] 4 2 10 1 11 2 12
[8,] 2 4 10 1 11 2 12
[9,] 2 4 10 2 11 1 12
[10,] 4 2 10 2 11 1 12
[11,] 2 2 10 4 11 1 12
[12,] 2 2 10 1 11 4 12