Rstudio:序列的for循环

h7appiyu  于 2023-09-27  发布在  其他
关注(0)|答案(2)|浏览(103)

我想找到数据形式的回溯序列(因为它是从Collatz猜想tibble数据从1到10,000)在某个点上超过该序列的起始值。
这是我的 Dataframe 输出:

structure(list(start = 1:6, seq = list(1L, c(2, 1), c(3, 10, 
5, 16, 8, 4, 2, 1), c(4, 2, 1), c(5, 16, 8, 4, 2, 1), c(6, 3, 
10, 5, 16, 8, 4, 2, 1)), length = c(1, 2, 8, 3, 6, 9), parity = c("Odd", 
"Even", "Odd", "Even", "Odd", "Even"), max_val = c(1, 2, 16, 
4, 16, 16)), row.names = c(NA, -6L), class = c("tbl_df", "tbl", 
"data.frame"))

我是这样做的:

has_backtrack <- function(seq) {
  length_seq <- length(seq)
  if (length_seq < 3) {
    return(FALSE)
  }
  for (i in 2:(length_seq - 1)) {
    if (seq[i] < seq[1] && seq[i + 1] > seq[i]) {
      return(TRUE)
    }
  }
}

然而,对于我目前的代码,它只显示序列是否增加,但不超过第一个值。
Backtracks def:当一个序列达到一个小于起始整数的值,但随后再次增加到起始值/整数之上时,它可以在达到1之前至少增加一次。

vuv7lop3

vuv7lop31#

考虑z作为第一个值之后的余数。在 idcumsum(z < x[1]) > 1)上设置z子集,并查看其中的any是否为TRUE

has_backtrack2 <- function(x) {
  if (length(x) < 3) FALSE
  else {
    z <- x[-1]
    any(z[cumsum(z < x[1]) > 1L] > x[1])
  }
}

使用sapply

sapply(df$seq, has_backtrack2)
# [1] FALSE FALSE FALSE FALSE FALSE  TRUE

或者是Vectorize d。

has_backtrack2v <- Vectorize(has_backtrack2)

has_backtrack2v(df$seq)
# [1] FALSE FALSE FALSE FALSE FALSE  TRUE

假设所需的“整数6”意味着which序列有回溯,你可以相应地得到它:

which(has_backtrack2v(df$seq))
# [1] 6
qvsjd97n

qvsjd97n2#

我不确定以下是你想要的。它使用R的向量化指令来获取输入序列在一条指令中增加的所有点,使代码变得更简单,没有for循环。
函数has_backtrack返回序列增加的点的索引,而不是序列值。
函数next_collatzcollatzthis R-bloggers code的启发。

next_collatz <- function(num) {
  if(num == 1L) {
    invisible(NULL)
  } else if(num %% 2L == 0L) {
    num / 2L
  } else 3L * num + 1L
}
collatz <- function(x) {
  result <- x
  while(x != 1L) {
    x <- next_collatz(x)
    result <- c(result, x)
  }
  result
}

has_backtrack <- function(x) which(diff(x) > 0L)

cltz_6 <- collatz(6)
has_backtrack(cltz_6)
#> [1] 2 4
i <- has_backtrack(cltz_6)
cltz_6[i]
#> [1] 3 5

创建于2023-09-24使用reprex v2.0.2
另一个例子,具有严格递减的输入Collatz序列。

(cltz_16 <- collatz(16))
#> [1] 16  8  4  2  1
(i <- has_backtrack(cltz_16))
#> integer(0)
cltz_16[i]
#> numeric(0)

创建于2023-09-24使用reprex v2.0.2

编辑

对于问题中发布的数据集,Collatz序列列是一个列表列,函数has_backtrack可以如下进行lapply编辑。
结果表明

  • 第1、2、4阶Collatz序列均为递减序列,没有指数指向递增点;
  • 第3和第6序列有两个序列增加的点;
  • 第五序列只有一个序列增加的点。
inx_list <- lapply(df1$seq, has_backtrack)
inx_list
#> [[1]]
#> integer(0)
#> 
#> [[2]]
#> integer(0)
#> 
#> [[3]]
#> [1] 1 3
#> 
#> [[4]]
#> integer(0)
#> 
#> [[5]]
#> [1] 1
#> 
#> [[6]]
#> [1] 2 4

创建于2023-09-24使用reprex v2.0.2
要获得增加点 * 之前的值,请使用Map

Map(\(x, i) x[i], df1$seq, inx_list)
#> [[1]]
#> integer(0)
#> 
#> [[2]]
#> numeric(0)
#> 
#> [[3]]
#> [1] 3 5
#> 
#> [[4]]
#> numeric(0)
#> 
#> [[5]]
#> [1] 5
#> 
#> [[6]]
#> [1] 3 5

创建于2023-09-24使用reprex v2.0.2

数据

df1 <-
  structure(list(
    start = 1:6, 
    seq = list(1L, c(2, 1), c(3, 10, 5, 16, 8, 4, 2, 1), 
               c(4, 2, 1), c(5, 16, 8, 4, 2, 1), c(6, 3, 10, 5, 16, 8, 4, 2, 1)), 
    length = c(1, 2, 8, 3, 6, 9), 
    parity = c("Odd", "Even", "Odd", "Even", "Odd", "Even"), 
    max_val = c(1, 2, 16, 4, 16, 16)), 
    row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"))

创建于2023-09-24使用reprex v2.0.2

相关问题