Как сделать специальную функцию перемешивания в php - PullRequest
2 голосов
/ 21 марта 2012

Мне нужна функция, которая рандомизирует массив, аналогичный тому, что делает случайное перемешивание, с той разницей, что каждый элемент имеет разные шансы.

Например, рассмотрим следующий массив:

$animals = array('elephant', 'dog', 'cat', 'mouse');

у слона больше шансов попасть на первый индекс, чем у собаки.Собака имеет больше шансов, чем кошка и так далее.Например, в этом конкретном примере у слона может быть 40% на 1-й позиции, 30% на 2-й, 20% на 3-й и 10% на последней.

Таким образом, после перетасовки первые элементы в исходном массиве с большей вероятностью (но не обязательно) будут в первых позициях, а последние - в последних позициях.

Ответы [ 3 ]

5 голосов
/ 22 марта 2012

Обычный случайный порядок может быть реализован так же, как

  • случайное выпадение предметов на некотором расстоянии
  • поднимая их слева направо

Мы можем настроить шаг опускания, опускать каждый элемент не во весь диапазон, а в какое-то скользящее окно. Пусть N будет количеством элементов в массиве, ширина окна будет w, и мы будем перемещать его на каждом шаге на off. Тогда off*(N-1) + w будет общей шириной диапазона.

Вот функция, которая искажает позиции элементов, но не полностью случайным образом.

function weak_shuffle($a, $strength) {
    $len = count($a);
    if ($len <= 1) return $a;
    $out = array();
    $M = mt_getrandmax();
    $w = round($M / ($strength + 1)); // width of the sliding window
    $off = ($M - $w) / ($len - 1); // offset of that window for each step.
    for ($i = 0; $i < $len; $i++) {
        do {
            $idx = intval($off * $i + mt_rand(0, $w));
        } while(array_key_exists($idx, $out));
        $out[$idx] = $a[$i];
    }
    ksort($out);
    return array_values($out);
}
  • $strength = 0 ~ обычный случайный порядок.
  • $strength = 0.25 ~ желаемый результат (40,5%, 25,5%, 22%, 12% для elephant)
  • $strength = 1 первый элемент никогда не будет после последнего.
  • $strength >= 3 массив фактически никогда не перемешивается

Площадка для тестирования:

$animals = array( 'elephant', 'dog', 'cat', 'mouse' );
$pos = array(0,0,0,0);
for ($iter = 0; $iter < 100000; $iter++) {
    $shuffled = weak_shuffle($animals, 0.25);
    $idx = array_search('elephant', $shuffled);
    $pos[$idx]++;
}
print_r($pos);
2 голосов
/ 22 марта 2012

Попробуйте использовать этот алгоритм:

$animals  = [ 'elephant', 'dog', 'cat', 'mouse' ]; // you can add more animals here
$shuffled = [];

$count = count($animals);

foreach($animals as $chance => $animal) {
    $priority = ceil(($count - $chance) * 100 / $count);
    $shuffled = array_merge($shuffled, array_fill(0, $priority, $animal));
}

shuffle($shuffled);
$animals = array_unique($shuffled);
1 голос
/ 22 марта 2012

У вас есть массив, скажем, из n элементов. Вероятность того, что i-й элемент перейдет в j-ю позицию, равна P (i, j). Если я правильно понял, справедлива следующая формула:

(P(i1, j1) >= P(i2, j2)) <=> (|i1 - j1| <= |j1 - i1|)

Таким образом, у вас есть связь Галуа между расстоянием в вашем массиве и вероятностью тасования. Вы можете использовать это соединение Galois для реализации вашей точной формулы, если она у вас есть. Если у вас нет формулы, вы можете изобрести ее, которая будет соответствовать критериям, указанным выше. Удачи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...