Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
всё, что надо делать участникам, — это записывать наборы натуральных чисел, а также вычёркивать из них отдельные элементы и вписывать новые.
В случае вытаскивания своего номера просто номер кладётся обратно, перемешивается и снова тащится случайный номер.Не все так просто. Если я вытащил свой номер — я знаю что его не вытащил никто до меня. А если я предпоследний, то я точно знаю кто мой санта.
церемония, пришедшая к нам с Запада
$user_ids = array();
foreach ($active_users as $i=>$u) {
$user_ids[] = $u['id'];
}
shuffle($user_ids);
foreach ($active_users as $i=>$u) {
$random_user_id = 0;
while (($random_user_id == 0) && (count($user_ids) > 0)) {
if ($user_ids[0] != $u['id']) {
$random_user_id = array_shift($user_ids);
$query = "UPDATE `adm`.`users` SET `victim`={$random_user_id} WHERE `id`=".$u['id'];
$res = mysql_query($query);
}
else {
shuffle($user_ids);
}
}
}
Не нужно никаких проверок — достаточно случайно перемешать линейный список участников, далее первый дарит второму, второй — третьему, ..., последний — первому. Ситуации дарения самому себе (при N>1) и отсутствия дарителя исключены.
ситуацию, когда третья сторона запрещена
Почему 3я сторона запрещена? Мы ведь в тайного Санту играем, а не в "передай подарок тайному агенту ЦРУ без привлечения ФСБ"
/**
* Перемешивание случайным образом массива чисел с учётом того,
* чтобы значения исходного и полученного массивов по идентичным индексам не дублировались
* @param array $list исходный массив чисел
* @return array перемешанный массив
*/
public static function randomArray($list) {
$target = array();
$used = array();
foreach ($list as $k=>$v) {
$tmp = $list;
//удаляем первое значение пары
unset($tmp[$k]);
//удаляем ранее использованные вторые значения пар
foreach ($used as $u)
if (($i = array_search($u, $tmp)) !== false)
unset($tmp[$i]);
$tk = array_rand($tmp);
$t = $tmp[$tk];
$target[$k] = $t;
$used[] = $t;
}
return $target;
}
Проблема в том, что одному или более участникам могут выпасть их собственные номера, что делает весь итоговый результат некорректным. Это большой минус алгоритма, так как вероятность попасть в эту ситуацию довольно высока, хотя она и падает с ростом N.
Алгоритм для секретного назначения дарителей в Secret Santa