【问题标题】:Solving Josephus permutation求解约瑟夫置换
【发布时间】:2018-07-20 02:14:09
【问题描述】:

假设如果有 100 个人按照 1 到 100 的顺序站成一圈。第 1 号有一把剑。他杀死了下一个人(即第 2 号)并将剑交给下一个(即第 3 号)。所有人都这样做,直到只有 1 人幸存。哪个数字最后存活?

从 1 到 100 有 100 人。

我试过了

persons <- c(1:100)
for (i in 1:100) {
  qu <- persons[seq_along(persons) %% 2 > 0]
  if (q2 == 2) {
    print(q2[2])
  }
}

还有这个

q=0
 while(q==0){ persons=persons[seq_along(persons) %% 2 > 0]
 if(length(persons)==2){ print(persons[2])
 q=1}}

但这给出的答案是 65,这是错误的,不能解决目的。

有什么办法可以做到这一点?

【问题讨论】:

标签: r for-loop


【解决方案1】:

在这个解决方案中,假设拿着剑的人是向量中的第一个人。该人杀死下一个人并移动到行尾。

如果只有一个人,那么那个人就是幸存者。

kill <- function(people = seq_len(100)) {
  if (length(people) == 1) return(people)

  kill(
    c(tail(people, -2), people[1]))
}


kill()
#> [1] 73

编辑:

对于较大的n,请使用以下solution

kill_fast <- function(n) 2 * (n - 2 ^ (floor(log2(n)))) + 1

kill_fast(100)
#> [1] 73

kill_fast(100000)
#> [1] 68929

【讨论】:

  • 是的,正确答案。如果可以请在if statement 中详细说明您的代码
  • if 语句只是检查是否只剩下一个人。如果有,那么我们返回那个人。否则,前两个人被删除,旧的第一人被添加到最后。然后同样的功能被应用到这组新的人身上。
【解决方案2】:

这是@Paul 以非递归方式重写的优雅答案,因此可能更容易理解。

people <- 1:100
while (length(people) > 1) {
  people <- c(people[-(1:2)], people[1])
}
print(people)
# [1] 73

【讨论】:

    【解决方案3】:

    这让一个人活着,但我不确定问题的限制

    persons=rep("ALIVE",100)
    for(i in 1:100) {
      if(i+1<101){
        if(persons[i+1]=="ALIVE"){
          persons[i]<-"DEAD"
        }
      }
      print(persons)
    }
    

    【讨论】:

      【解决方案4】:

      我不是不喜欢递归,但这里有一个更通用的解决方案,适用于任何人口规模:

      kill <- function(n = 100) {
        seq1 <- 2 ^ seq_len(31)
        seq2 <- n / seq1
        seq2 <- c(n, floor(seq2[seq2 >= 3]))
        sum(seq1[1:length(seq2)][seq2 %% 2 == 1], 1)
      }
      

      现在你可以看到,如果我们在大约 800 万瑞士人中玩这个,我应该排在位置 7'611'393... (kill(8000000))

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多