将每个值交换为不同的值

时间:2018-08-02 11:32:15

标签: r

下面是交换函数,它交换列表中小于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的其他值。

如果没有可行的解决方案,只需打印“没有可行的解决方案”

有什么建议吗? 非常感谢。

2 个答案:

答案 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)

此功能为您提供数字 = m的位置相同。

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