Ще ви трябва нещо, което е правилно по конструкция, т.е. пермутационна функция:това е функция, която извършва едно към едно, обратимо съпоставяне на едно цяло число (вашия последователен брояч) на друго. Някои примери (всяка комбинация от тях също трябва работа):
- обръщане на някои от битовете (например с помощта на XOR, ^ в PHP)
- размяна на местата на битовете (($i &0xc)>> 2 | ($i &0x3) <<2) или просто обръщане на реда на всички битове
- добавяне на постоянна стойност по модул към максималния ви обхват (трябва да е коефициент два, ако комбинирате това с горните)
Пример:тази функция ще преобразува 0, 1, 2, 3, 5, .. в 13, 4, 12, 7, 15, .. за числа до 15:
$i=($input+97) & 0xf;
$result=((($i&0x1) << 3) + (($i&0xe) >> 1)) ^ 0x5;
РЕДАКТИРАНЕ
По-лесен начин би бил да се използва линеен конгруентен генератор (LCG, който обикновено се използва за генериране на произволни числа), който се дефинира с формула от вида:
X_n+1 = (a * X_n + c) mod m
За добри стойности от a, c и m, последователността от X_0, X_1 .. X_m-1 ще съдържа всички числа между 0 и m-1 точно веднъж. Сега можете да започнете от линейно нарастващ индекс и да използвате следващия стойност в LCG последователността като ваш "таен" ключ.
РЕДАКТИРАНЕ2
Внедряване:Можете да проектирате свои собствени LCG параметри , но ако сбъркате, няма да покрие пълния диапазон (и по този начин ще има дубликати), така че ще използвам публикуван и изпробван набор от параметри тук от този документ :
a = 16807, c = 0, m = 2147483647
Това ви дава диапазон от 2**31. С pack() можете да получите полученото цяло число като низ, base64_encode() го прави четим низ (от до 6 значими знака, 6 бита на байт), така че това може да е вашата функция:
substr(base64_encode(pack("l", (16807 * $index) % 2147483647)), 0, 6)