Решение перестановки Джозефуса

Предположим, что 100 человек, стоящих по кругу в порядке от 1 до 100. № 1 имеет меч. Он убивает следующего человека (т.е. № 2) и дает меч следующему (т.е. № 3). Все люди делают то же самое, пока не выживет только 1 человек. Какое число сохранилось в последний раз?

Есть 100 человек, начиная от 1 до 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}}

Но это дает ответ, который неверен и не решает цель.

Любое решение, как это можно сделать?

Ответы

Ответ 1

В этом решении предположим, что человек с мечом является первым человеком в векторе. Этот человек убивает следующего человека и переходит к концу линии.

Если есть один человек, то этот человек является выжившим.

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

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


kill()
#> [1] 73

Редактировать:

Для больших n используйте следующее решение

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

kill_fast(100)
#> [1] 73

kill_fast(100000)
#> [1] 68929

Ответ 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)
}

Теперь вы можете видеть, что если бы мы сыграли это среди нас примерно 8 миллионов швейцарцев, я должен был выстроиться в позиции 7'611'393... (kill(8000000))