<?php
function factorial($value) {
return array_reduce(range(1, $value), function($carry,$item){return $carry*$item;}, 1); }
function R($value) {
}
function make_chain($start, $length) {
$chain['start'] = $start;
for($i = 0; $i < $length; ++$i) {
$hash = factorial($start);
echo ">>> $start! == $hash\n"; // диагностическое сообщение
$start = R($hash);
if($start == 0) break;
}
$chain['end'] = $hash;
echo "Chain from ${chain['start']} to ${chain['end']} is ready.\n"; // диагностическое сообщение
return $chain;
}
function make_chains($count, $length) {
$chains = [];
for($i = 0; $i < $count; ++$i) {
$number = mt_rand(0, MAX_NUMBER
- 1); // начинаем цепочку с псевдослучайного слова $chain = make_chain($number, $length);
$hash = $chain['end']; // используем конец найденной цепочки как индекс для быстрого поиска
if(!isset($chains[$hash])) $chains[$hash] = []; // если такого хэша не было в корзине, инициализируем её if(!in_array($chain['start'], $chains[$hash])) { // проверяем на дубли $chains[$hash][] = $chain['start']; // добавляем начало цепочки в корзину
}
}
return $chains;
}
function find_hash_in_basket($needle, $haystack_start, $haystack_end) {
echo "Роемся в цепочке от $haystack_start до $haystack_end.\n"; // диагностическое сообщение
$current_number = $haystack_start;
do {
$current_hash = factorial($current_number); // <-- сюда вставьте нужную хэш-функцию
if($current_hash <= $needle && $needle <= $current_hash * ($current_number + 1)) {
return $current_number; // нашли
}
$current_number = R($current_hash); // роем в глубину
} while($current_hash !== $haystack_end);
return false; // не нашли
}
function search_hash($hash, $chains, $length) {
$current_hash = $hash;
for($i = 0; $i < $length; ++$i) {
if(isset($chains[$current_hash])) { // нашли хэш в одной из корзин echo "Лезем в корзину $current_hash.\n"; // диагностическое сообщение
foreach($chains[$current_hash] as $start) { // роемся в корзине
$result = find_hash_in_basket($hash, $start, $current_hash); // пытаемся найти в каждой из цепочек корзины
if($result) {
return $result; // конец поиска
}
}
}
$next_number = R($current_hash); // копаем в глубину
$current_hash = factorial($next_number);
}
return false; // не нашли
}
///////////////////// ПРИМЕР //////////////////////////////////
$chains = make_chains(10, 5);
echo "Радужные таблицы готовы.\n";
$hash = 721;
echo "Пытаемся обратить $hash.\n";
$number = search_hash($hash, $chains, 5);
echo $number . "! <= $hash <= " . ($number+1) . "!\n";
PD9waHAKCmRlZmluZSgnTUFYX05VTUJFUicsIDcwKTsKCmZ1bmN0aW9uIGZhY3RvcmlhbCgkdmFsdWUpIHsKICAgIHJldHVybiBhcnJheV9yZWR1Y2UocmFuZ2UoMSwgJHZhbHVlKSwgZnVuY3Rpb24oJGNhcnJ5LCRpdGVtKXtyZXR1cm4gJGNhcnJ5KiRpdGVtO30sIDEpOwp9CgpmdW5jdGlvbiBSKCR2YWx1ZSkgewogICAgcmV0dXJuIGZsb29yKDIqc3FydChsb2coKCR2YWx1ZSkpKSk7Cn0KCmZ1bmN0aW9uIG1ha2VfY2hhaW4oJHN0YXJ0LCAkbGVuZ3RoKSB7CiAgICAkY2hhaW5bJ3N0YXJ0J10gPSAkc3RhcnQ7CiAgICBmb3IoJGkgPSAwOyAkaSA8ICRsZW5ndGg7ICsrJGkpIHsKICAgICAgICAkaGFzaCA9IGZhY3RvcmlhbCgkc3RhcnQpOwogICAgICAgIGVjaG8gIj4+PiAkc3RhcnQhID09ICRoYXNoXG4iOyAgICAgICAgICAgIC8vINC00LjQsNCz0L3QvtGB0YLQuNGH0LXRgdC60L7QtSDRgdC+0L7QsdGJ0LXQvdC40LUKICAgICAgICAkc3RhcnQgPSBSKCRoYXNoKTsKICAgICAgICBpZigkc3RhcnQgPT0gMCkgYnJlYWs7CiAgICB9CiAgICAkY2hhaW5bJ2VuZCddID0gJGhhc2g7CiAgICBlY2hvICJDaGFpbiBmcm9tICR7Y2hhaW5bJ3N0YXJ0J119IHRvICR7Y2hhaW5bJ2VuZCddfSBpcyByZWFkeS5cbiI7IC8vINC00LjQsNCz0L3QvtGB0YLQuNGH0LXRgdC60L7QtSDRgdC+0L7QsdGJ0LXQvdC40LUKICAgIHJldHVybiAkY2hhaW47Cn0KCmZ1bmN0aW9uIG1ha2VfY2hhaW5zKCRjb3VudCwgJGxlbmd0aCkgewogICAgJGNoYWlucyA9IFtdOwogICAgbXRfc3JhbmQoKTsKICAgIGZvcigkaSA9IDA7ICRpIDwgJGNvdW50OyArKyRpKSB7CiAgICAgICAgJG51bWJlciA9IG10X3JhbmQoMCwgTUFYX05VTUJFUiAtIDEpOyAgICAgICAgICAgICAgICAvLyDQvdCw0YfQuNC90LDQtdC8INGG0LXQv9C+0YfQutGDINGBINC/0YHQtdCy0LTQvtGB0LvRg9GH0LDQudC90L7Qs9C+INGB0LvQvtCy0LAKICAgICAgICAkY2hhaW4gPSBtYWtlX2NoYWluKCRudW1iZXIsICRsZW5ndGgpOwogICAgICAgICRoYXNoID0gJGNoYWluWydlbmQnXTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8g0LjRgdC/0L7Qu9GM0LfRg9C10Lwg0LrQvtC90LXRhiDQvdCw0LnQtNC10L3QvdC+0Lkg0YbQtdC/0L7Rh9C60Lgg0LrQsNC6INC40L3QtNC10LrRgSDQtNC70Y8g0LHRi9GB0YLRgNC+0LPQviDQv9C+0LjRgdC60LAKICAgICAgICBpZighaXNzZXQoJGNoYWluc1skaGFzaF0pKSAkY2hhaW5zWyRoYXNoXSA9IFtdOyAgICAgIC8vINC10YHQu9C4INGC0LDQutC+0LPQviDRhdGN0YjQsCDQvdC1INCx0YvQu9C+INCyINC60L7RgNC30LjQvdC1LCDQuNC90LjRhtC40LDQu9C40LfQuNGA0YPQtdC8INC10ZEKICAgICAgICBpZighaW5fYXJyYXkoJGNoYWluWydzdGFydCddLCAkY2hhaW5zWyRoYXNoXSkpIHsgICAgIC8vINC/0YDQvtCy0LXRgNGP0LXQvCDQvdCwINC00YPQsdC70LgKICAgICAgICAgICAgJGNoYWluc1skaGFzaF1bXSA9ICRjaGFpblsnc3RhcnQnXTsgICAgICAgICAgICAgIC8vINC00L7QsdCw0LLQu9GP0LXQvCDQvdCw0YfQsNC70L4g0YbQtdC/0L7Rh9C60Lgg0LIg0LrQvtGA0LfQuNC90YMKICAgICAgICB9CiAgICB9CiAgICByZXR1cm4gJGNoYWluczsKfQoKZnVuY3Rpb24gZmluZF9oYXNoX2luX2Jhc2tldCgkbmVlZGxlLCAkaGF5c3RhY2tfc3RhcnQsICRoYXlzdGFja19lbmQpIHsKICAgIGVjaG8gItCg0L7QtdC80YHRjyDQsiDRhtC10L/QvtGH0LrQtSDQvtGCICRoYXlzdGFja19zdGFydCDQtNC+ICRoYXlzdGFja19lbmQuXG4iOyAgICAgICAvLyDQtNC40LDQs9C90L7RgdGC0LjRh9C10YHQutC+0LUg0YHQvtC+0LHRidC10L3QuNC1CiAgICAkY3VycmVudF9udW1iZXIgPSAkaGF5c3RhY2tfc3RhcnQ7CiAgICBkbyB7CiAgICAgICAgJGN1cnJlbnRfaGFzaCA9IGZhY3RvcmlhbCgkY3VycmVudF9udW1iZXIpOyAgICAgICAgIC8vIDwtLSDRgdGO0LTQsCDQstGB0YLQsNCy0YzRgtC1INC90YPQttC90YPRjiDRhdGN0Ygt0YTRg9C90LrRhtC40Y4KICAgICAgICBpZigkY3VycmVudF9oYXNoIDw9ICRuZWVkbGUgJiYgJG5lZWRsZSA8PSAkY3VycmVudF9oYXNoICogKCRjdXJyZW50X251bWJlciArIDEpKSB7CiAgICAgICAgICAgICByZXR1cm4gJGN1cnJlbnRfbnVtYmVyOyAgICAgICAgICAgICAgICAgIC8vINC90LDRiNC70LgKICAgICAgICB9CiAgICAgICAgJGN1cnJlbnRfbnVtYmVyID0gUigkY3VycmVudF9oYXNoKTsgIC8vINGA0L7QtdC8INCyINCz0LvRg9Cx0LjQvdGDCiAgICB9IHdoaWxlKCRjdXJyZW50X2hhc2ggIT09ICRoYXlzdGFja19lbmQpOwogICAgcmV0dXJuIGZhbHNlOyAvLyDQvdC1INC90LDRiNC70LgKfQoKZnVuY3Rpb24gc2VhcmNoX2hhc2goJGhhc2gsICRjaGFpbnMsICRsZW5ndGgpIHsKICAgICRjdXJyZW50X2hhc2ggPSAkaGFzaDsKICAgIGZvcigkaSA9IDA7ICRpIDwgJGxlbmd0aDsgKyskaSkgewogICAgICAgICAgaWYoaXNzZXQoJGNoYWluc1skY3VycmVudF9oYXNoXSkpIHsgICAgICAgICAgICAgICAgLy8g0L3QsNGI0LvQuCDRhdGN0Ygg0LIg0L7QtNC90L7QuSDQuNC3INC60L7RgNC30LjQvQogICAgICAgICAgICAgIGVjaG8gItCb0LXQt9C10Lwg0LIg0LrQvtGA0LfQuNC90YMgJGN1cnJlbnRfaGFzaC5cbiI7ICAgICAgIC8vINC00LjQsNCz0L3QvtGB0YLQuNGH0LXRgdC60L7QtSDRgdC+0L7QsdGJ0LXQvdC40LUKICAgICAgICAgICAgICBmb3JlYWNoKCRjaGFpbnNbJGN1cnJlbnRfaGFzaF0gYXMgJHN0YXJ0KSB7ICAgIC8vINGA0L7QtdC80YHRjyDQsiDQutC+0YDQt9C40L3QtQogICAgICAgICAgICAgICAgICAkcmVzdWx0ID0gZmluZF9oYXNoX2luX2Jhc2tldCgkaGFzaCwgJHN0YXJ0LCAkY3VycmVudF9oYXNoKTsgLy8g0L/Ri9GC0LDQtdC80YHRjyDQvdCw0LnRgtC4INCyINC60LDQttC00L7QuSDQuNC3INGG0LXQv9C+0YfQtdC6INC60L7RgNC30LjQvdGLCiAgICAgICAgICAgICAgICAgIGlmKCRyZXN1bHQpIHsKICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAkcmVzdWx0OyAgICAgICAgICAgICAgICAgICAgICAgIC8vINC60L7QvdC10YYg0L/QvtC40YHQutCwCiAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICB9CiAgICAgICAgICB9CiAgICAgICAgICAkbmV4dF9udW1iZXIgPSBSKCRjdXJyZW50X2hhc2gpOyAgICAgICAgICAgICAvLyDQutC+0L/QsNC10Lwg0LIg0LPQu9GD0LHQuNC90YMKICAgICAgICAgICRjdXJyZW50X2hhc2ggPSBmYWN0b3JpYWwoJG5leHRfbnVtYmVyKTsKICAgIH0KICAgIHJldHVybiBmYWxzZTsgLy8g0L3QtSDQvdCw0YjQu9C4Cn0KCi8vLy8vLy8vLy8vLy8vLy8vLy8vLyDQn9Cg0JjQnNCV0KAgLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwoKCiRjaGFpbnMgPSBtYWtlX2NoYWlucygxMCwgNSk7CmVjaG8gItCg0LDQtNGD0LbQvdGL0LUg0YLQsNCx0LvQuNGG0Ysg0LPQvtGC0L7QstGLLlxuIjsKdmFyX2R1bXAoJGNoYWlucyk7CgokaGFzaCA9IDcyMTsKZWNobyAi0J/Ri9GC0LDQtdC80YHRjyDQvtCx0YDQsNGC0LjRgtGMICRoYXNoLlxuIjsKJG51bWJlciA9IHNlYXJjaF9oYXNoKCRoYXNoLCAkY2hhaW5zLCA1KTsKZWNobyAkbnVtYmVyIC4gIiEgPD0gJGhhc2ggPD0gIiAuICgkbnVtYmVyKzEpIC4gIiFcbiI7Cg==