Решение:
function id_encode($id, $chars) {
$len = strlen($chars);
$i = 1;
$str = array();
while ($id >= 0) {
$str[] = $chars[ $id / pow($len, $i - 1) % $len ];
$id -= pow($len, $i);
$i++;
}
return strrev(implode('', $str));
}
function id_decode($str, $chars) {
$len = strlen($chars);
$chars = array_flip(str_split($chars));
$strs = str_split(strrev($str));
$i = 0;
foreach ($strs as $key => $char) {
if (!$i) {
$id = $chars[ $char ];
}
else {
$id += pow($len, $i) * ($chars[ $char ] + 1);
}
$i++;
}
return $id;
}
Пример:
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_';
$id = 42599293;
$string = id_encode($id, $chars);
echo 'id: ' . $id . PHP_EOL;
echo 'id_encode(): ' . $string . PHP_EOL;
echo 'id_decode(): ' . id_decode($string, $chars) . PHP_EOL;
Выход:
id: 42599293
id_encode(): bHFm9
id_decode(): 42599293
Пример 2:
$chars = 'AB';
$len = strlen($chars);
for ($i = 0; $i < 50; $i++) {
if ($i) {
if (!($i % $len)) {
echo PHP_EOL;
}
else {
echo ', ';
}
}
$str = id_encode($i, $chars);
$id = id_decode($str, $chars);
echo $i . '=' . $str . '=' . $id;
}
Выход 2:
0=A=0, 1=B=1
2=AA=2, 3=AB=3
4=BA=4, 5=BB=5
6=AAA=6, 7=AAB=7
8=ABA=8, 9=ABB=9
10=BAA=10, 11=BAB=11
12=BBA=12, 13=BBB=13
14=AAAA=14, 15=AAAB=15
16=AABA=16, 17=AABB=17
18=ABAA=18, 19=ABAB=19
20=ABBA=20, 21=ABBB=21
22=BAAA=22, 23=BAAB=23
24=BABA=24, 25=BABB=25
26=BBAA=26, 27=BBAB=27
28=BBBA=28, 29=BBBB=29
30=AAAAA=30, 31=AAAAB=31
32=AAABA=32, 33=AAABB=33
34=AABAA=34, 35=AABAB=35
36=AABBA=36, 37=AABBB=37
38=ABAAA=38, 39=ABAAB=39
40=ABABA=40, 41=ABABB=41
42=ABBAA=42, 43=ABBAB=43
44=ABBBA=44, 45=ABBBB=45
46=BAAAA=46, 47=BAAAB=47
48=BAABA=48, 49=BAABB=49
Кредит на id_encode()
переходит к @PatrickLorio. id_decode()
был построен мной с вычислениями вручную:
![enter image description here](https://i.stack.imgur.com/6Bgyo.jpg)
После этого я думаю, что можно оптимизировать id_encode()
, взяв n-й корень идентификатора ... возможно, я найду время, чтобы проверить это.