Решающий алгоритм (перестановка Джозефуса) в PHP

1

Предположим, 100 человек выстроились в круг. Подсчитав от человека 1 к человеку 14, удалите человека из круга. Следуя порядку подсчета, снова подсчитываем и удаляем 14-го человека. Повторение. Кто последний человек стоит?

Я пробовал все, чтобы решить эту проблему, и, похоже, она не работает с мертвыми петлями.

<?php
//init array
$array = array();
for ($i = 0; $i < 100; $i++) { $array[] = $i; }

//start from 0
$pos = 0;
while (count_not_null($array) > 1) {
    //reset count
    $count = 0;
    while (true) {
        //ignore NULL for count, that position is already removed
        if ($array[$pos] !== NULL) {
            $count++;
            if($count == 14) { break; }
        }
        $pos++;
        //go back to beginning, we cant go over 0-99, for 100 elements
        if ($pos > 99) { $pos = 0; }
    }
    echo "set index {$pos} to NULL!" ."<br>";
    $array[$pos] = NULL;
    if (count_not_null($array) === 1) { break; }
}

echo "<pre>";
print_r($array);
echo "</pre>";


//counting not null elements
function count_not_null($array) {
    $count = 0;
    for ($i = 0; $i < count($array); $i++) {
        if ($array[$i] !== NULL) { $count++; }
    }
    return $count;
}
?>
  • 2
    Какое поведение вы видите и почему это не соответствует вашим ожиданиям?
  • 0
    if ($ array [$ pos]! = NULL) {$ count ++; } Я уже пропускаю NULL, не считается как, поскольку NULL для меня считается человеком, уже удаленным.
Показать ещё 7 комментариев
Теги:
algorithm
josephus

2 ответа

3
Лучший ответ

Для решения этой проблемы, используя как можно меньше и наименьший код, вы можете сделать следующее:

function josephus($n,$k){
    if($n ==1)
        return 1;
    else
        return (josephus($n-1,$k)+$k-1) % $n+1;
}

echo josephus(100,14);

Здесь мы вместо этого используем рекурсивный оператор, поскольку то, что вы пытаетесь решить, может быть определено этим математическим утверждением f(n,k) = (f(n-1,k) + k) % n
Для получения дополнительной информации об этой математической формуле вы можете увидеть ее здесь на странице wiki.

2

Проблема в том, что цикл while

    while ($count < 14) {
        if ($array[$pos] != NULL) {
            $count++;
        }
        $pos++;
        if ($pos > 99) { $pos = 0; }
    }

Поскольку вы увеличиваете $ pos, даже если count равен 14, вы закончите с неверными значениями и цикл навсегда. Замените его следующим:

    while (true) {
        if ($array[$pos] != NULL) {
            $count++;
            if($count == 14) {break;}
        }
        $pos++;
        if ($pos > 99) { $pos = 0; }
    }

Также сравнение 0 с NULL не даст вам ожидаемых результатов, как указано @Barmar, поэтому вы можете либо изменить сравнение NULL, либо начать отсчет с 1

ПРИМЕЧАНИЕ. Это было бы намного быстрее, если бы каждый цикл не выполнялся через массив: D подумайте об использовании переменной, чтобы подсчитать оставшиеся элементы

  • 0
    ты прав, моя проблема решена, ты очень

Ещё вопросы

Сообщество Overcoder
Наверх
Меню