Решение перестановки Джозефуса
Предположим, что 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)
)