繁体   English   中英

Function 用于 R 中的二进制序列

[英]Function for binary sequences in R

如何在 R 中写一个 function 给定一个 integer n,它找到所有长度为 2n 的二进制序列,使得最后 n 位的总和与第一个 n 位相同。

Example:
For   n = 2, the sequences are:
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    0    1    1    0    0    1
[2,]    0    0    0    1    1    1
[3,]    0    1    0    1    0    1
[4,]    0    0    1    0    1    1

以下 function 是GeeksforGeeks 帖子中函数的 R 翻译。

findAllSeq2n <- function(n){
  f <- function(d, out, start, end){
    if (abs(d) > (end - start + 1) / 2) return(NULL)
    if (start > end) { 
      if (d == 0) {
        #cat(out, "\n")
        return(out)
      }
    }

    out[start] <- 0L
    out[end] <- 1L
    s01 <- f(d + 1L, out, start + 1L, end - 1L)
    
    out[start] <- 1L
    out[end] <- 1L
    s11 <- f(d, out, start + 1L, end - 1L)
    
    out[start] <- 0L
    out[end] <- 0L
    s00 <- f(d, out, start + 1L, end - 1L)
    
    out[start] <- 1L
    out[end] <- 0L
    s10 <- f(d - 1L, out, start + 1L, end - 1L)

    do.call(cbind, list(s01, s11, s00, s10))
  }
  out <- integer(2*n)
  f(0, out, 1, 2*n)
}

findAllSeq2n(2)
#     [,1] [,2] [,3] [,4] [,5] [,6]
#[1,]    0    1    1    0    0    1
#[2,]    1    1    0    1    0    0
#[3,]    0    1    0    1    0    1
#[4,]    1    1    1    0    0    0

findAllSeq2n(3)
findAllSeq2n(4)

这是一个简单的解决方案。

f <- function(n){
    bit_list <- rep(list(0:1),2*n)
    df <- expand.grid(bit_list)
    result <- df %>% filter(rowSums(df[1:n]) == rowSums(df[(n+1):(2*n)]))
    return(result)
  }

这是使用expand.grid的基本 R 选项

f_TIC <- function(n) {
  df <- expand.grid(rep(list(0:1), n))
  do.call(
    cbind,
    Map(
      function(x) {
        v <- unname(as.matrix(x))
        inds <- expand.grid(rep(list(seq(nrow(v))), 2))
        with(inds, t(cbind(v[Var1, , drop = FALSE], v[Var2, , drop = FALSE])))
      },
      split(df, rowSums(df))
    )
  )
}

你会看到

> f_TIC(2)
     [,1] [,2] [,3] [,4] [,5] [,6]
[1,]    0    1    0    1    0    1
[2,]    0    0    1    0    1    1
[3,]    0    1    1    0    0    1
[4,]    0    0    0    1    1    1

> f_TIC(3)
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13] [,14]
[1,]    0    1    0    0    1    0    0    1    0     0     1     1     0     1
[2,]    0    0    1    0    0    1    0    0    1     0     1     0     1     1
[3,]    0    0    0    1    0    0    1    0    0     1     0     1     1     0
[4,]    0    1    1    1    0    0    0    0    0     0     1     1     1     1
[5,]    0    0    0    0    1    1    1    0    0     0     1     1     1     0
[6,]    0    0    0    0    0    0    0    1    1     1     0     0     0     1
     [,15] [,16] [,17] [,18] [,19] [,20]
[1,]     1     0     1     1     0     1
[2,]     0     1     1     0     1     1
[3,]     1     1     0     1     1     1
[4,]     1     1     0     0     0     1
[5,]     0     0     1     1     1     1
[6,]     1     1     1     1     1     1

基准测试对帖子的所有给出的答案如下

f_TIC <- function(n) {
  df <- expand.grid(rep(list(0:1), n))
  do.call(
    cbind,
    Map(
      function(x) {
        v <- unname(as.matrix(x))
        inds <- expand.grid(rep(list(seq(nrow(v))), 2))
        with(inds, t(cbind(v[Var1, , drop = FALSE], v[Var2, , drop = FALSE])))
      },
      split(df, rowSums(df))
    )
  )
}

f_PW <- function(n) {
  bit_list <- rep(list(0:1), 2 * n)
  df <- expand.grid(bit_list)
  result <- df %>% filter(rowSums(df[1:n]) == rowSums(df[(n + 1):(2 * n)]))
  return(result)
}

f_RB <- function(n) {
  f <- function(d, out, start, end) {
    if (abs(d) > (end - start + 1) / 2) {
      return(NULL)
    }
    if (start > end) {
      if (d == 0) {
        # cat(out, "\n")
        return(out)
      }
    }

    out[start] <- 0L
    out[end] <- 1L
    s01 <- f(d + 1L, out, start + 1L, end - 1L)

    out[start] <- 1L
    out[end] <- 1L
    s11 <- f(d, out, start + 1L, end - 1L)

    out[start] <- 0L
    out[end] <- 0L
    s00 <- f(d, out, start + 1L, end - 1L)

    out[start] <- 1L
    out[end] <- 0L
    s10 <- f(d - 1L, out, start + 1L, end - 1L)

    do.call(cbind, list(s01, s11, s00, s10))
  }
  out <- integer(2 * n)
  f(0, out, 1, 2 * n)
}

你会看见

Unit: relative
     expr      min        lq     mean    median        uq       max neval
 f_TIC(8)  1.00000  1.000000  1.00000  1.000000  1.000000  1.000000   100
  f_PW(8)  3.00963  2.982558  3.04141  3.048198  3.414973  1.708085   100
  f_RB(8) 33.84919 33.294016 29.94054 31.868353 30.959561 15.716849   100

Unit: relative
     expr      min       lq     mean   median       uq      max neval
 f_TIC(5) 1.429396 1.454938 1.395263 1.435046 1.427896 1.284587   100
  f_PW(5) 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000   100
  f_RB(5) 1.964645 1.997190 2.032348 1.973493 1.932053 3.413937   100

Unit: relative
     expr      min       lq     mean   median       uq       max neval
 f_TIC(2) 17.08527 16.34189 3.558179 14.19286 13.83643 0.4397982   100
  f_PW(2) 17.50388 16.96616 4.020926 14.90068 14.66048 0.4361216   100
  f_RB(2)  1.00000  1.00000 1.000000  1.00000  1.00000 1.0000000   100

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM