Генерация уникальной комбинации средствами php?

Требуется сгенерировать уникальную комбинацию.
Комбинация состоит из 16 цифр, каждая цифра в диапазоне от 1 до 10.
Пример: 1 9 2 6 10 9 3 7 1 3 9 10 3 6 10 2

Перепробовал кучу различных вариантов рандома - многие из них на тесте 10к комбинаций генерируют одинаковые. Игрался с mt_srand() и прочими вещами. Идеального решения найти так и не смог.

10^16 показывает очень большое кол-во возможных комбинаций (если я помню школьный курс информатики). Но когда на 50к 16к дубликатов - это неочем. В самом глупом рандоме получалось на 10к - 200 дубликатов.

В базе на поле с комбинацией лежит индекс unique, поэтому очень не хотелось бы пропускать комбинации. Или хотя бы свести кол-во дубликатов по минимуму.
Какие есть варианты генерации ?
  • Вопрос задан
  • 4009 просмотров
Пригласить эксперта
Ответы на вопрос 5
Вы должны понимать, что случайные значения - на то и случайные, они повторяются и их нельзя генерить для уникальных полей. Используете автоинкремент.
Ответ написан
Очевидно, псевдослучайные числа - не лучший способ получать уникальный ключ.
Но по существу такой код:
function getRandSeq($seq_len) {
    $result = array();
    for ($i=1; $i<=$seq_len; $i++)
        $result[] = rand(1, 10);
    return implode(" ", $result);    
}
function getMtRandSeq($seq_len) {
    $result = array();
    for ($i=1; $i<=$seq_len; $i++)
        $result[] = mt_rand(1, 10);
    return implode(" ", $result);    
}
//
$total = 50000;
$seq_arr1 = array();
$seq_arr2 = array();
$dbl_count1 = 0;
$dbl_count2 = 0;
for ($t=1; $t<=$total; $t++) {
    $seq1 = getRandSeq(16);
    $seq2 = getMtRandSeq(16);    
    if (in_array($seq1, $seq_arr1))
        $dbl_count1++;
    if (in_array($seq2, $seq_arr2))
        $dbl_count2++;           
    $seq_arr1[] = $seq1;
    $seq_arr2[] = $seq2;    
}
echo $dbl_count1."/".$dbl_count2."/".$total;

Вернул мне:
47952/0/50000

Т.е. на 50к генераций rand даёт кучу повторов, а вот mt_rand - 0.
Ответ написан
Комментировать
deadbyelpy
@deadbyelpy
веб-шмеб
Может есть возможность использовать функцию UUID ?
Правда формат может быть неподходящим.

2 вариант, не производительный ,генерация числа в цикле с запросами на уникальность к бд, не уникальный, значит генерим новый.
Ответ написан
Комментировать
egor_nullptr
@egor_nullptr
Попробуйте генерировать числа от 10^15 до 10^16-1 вместо комбинаций.
Ответ написан
Комментировать
@Masterme
энтропия в юниксах находится в /dev/random
правда, количество её ограничено, придётся ждать
либо использовать /dev/urandom

вам нужно получить не 16 чисел от 1 до 10, а одну последовательность длиной примерно 50 бит (то есть, это получится 50-значное число с основанием 2, его можно преобразовать в число с основанием 10)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы