его вариант несовсем корректен. некоторые значения при переборе он невыводит, например 'aaa'. это так на вскидку. чтото сложные у вас решения какието. много букв ))) Код (PHP): $dict = 'abx1'; // словарь символов для перебора define('DICTLEN', strlen($dict) ); // длина словаря $cur = 'aa'; // значение с которого надо начать $end = 'aaaa'; // значение на которым закончить перебор // поехали! while($cur!=$end) { for($i=strlen($cur)-1; $i>=0; --$i) { $pos = strpos($dict, $cur[$i]); if ($pos==DICTLEN-1) { // no next if ($i==0) { // limit left $cur = $dict[0].str_repeat($dict[0],strlen($cur)); } else { // not limit left $pos2 = strpos($dict, $cur[$i-1]); if ($pos2==DICTLEN-1) continue; $cur[$i-1] = $dict[$pos2+1]; $cur = substr_replace($cur, str_repeat($dict[0],strlen($cur)-$i),$i); } } else $cur[$i] = $dict[$pos+1]; // exist break; } // for echo $cur.'<br>'; // если нужен массив то: str_split($cur); } // while
ой, баг вместо Код (PHP): if (!isset($pointers[$index + 1])) { $pointers[$index + 1] = 0; } $pointers[$index + 1]++; надо Код (PHP): if (!isset($pointers[$index + 1])) { $pointers[$index + 1] = 0; } else { $pointers[$index + 1]++; } поправил Код (PHP): <?php $chars = ['a', 'b', 'x', '1']; $word = '1a'; if (empty($word)) { $pointers = [0]; } else { $we = str_split($word); $we = array_reverse($we); //$pointers[0] - правый символ foreach ($we as $w) { foreach ($chars as $ck => $cv) { if ($w === $cv) { $pointers[] = $ck; } } } } $cmax = count($chars) - 1; for ($i = 0; $i < 10; $i++) { $pointers = iter($pointers, $cmax); echo buildWord($pointers, $chars), '<br>'; } function buildWord($pointers, $chars) { $word = ''; $pointers = array_reverse($pointers); foreach ($pointers as $p) { $word .= $chars[$p]; } return $word; } function iter($pointers, $cmax) { $pointers[0]++; var_dump($pointers); reset($pointers); $flag = true; $index = 0; do { if ($pointers[$index] <= $cmax) { $flag = false; } else { $pointers[$index] = 0; if (!isset($pointers[$index + 1])) { $pointers[$index + 1] = 0; } else { $pointers[$index + 1]++; } } $index++; } while ($flag == true); return $pointers; }
igordata, это Код (PHP): foreach ($we as $w) { foreach ($chars as $ck => $cv) { if ($w === $cv) { $pointers[] = $ck; } } } можно заменить на Код (PHP): foreach ($we as $w) { $pointers[] = array_search($w,$chars); }
провел рефакторинг, оптимайзинг и ускоринг) Код (PHP): $dict = 'abx1'; // словарь символов для перебора $dict_ = array_flip(str_split($dict)); // вспомогательный массив define('DICTLEN', strlen($dict)-1 ); // длина словаря $cur = '1a'; // значение с которого надо начать $end = 'aaaaa'; // значение на которым закончить перебор while($cur!=$end) { for($i=strlen($cur)-1; $i>=0; --$i) { if ($dict_[$cur[$i]]<DICTLEN) { $cur[$i] = $dict[$dict_[$cur[$i]]+1]; } else { $cur[$i] = $dict[0]; if ($i>0) continue; $cur = $dict[0].$cur; } break; } // for echo $cur.'<br>'; // если нужен массив то: str_split($cur); } // while
тем что переменную можно случайно перезаписать. чтоб подстраховать себя от лишних багов с этим связанных, в процессе кодинга алгоритма. а так более ничем. да и логичнее так. если она недолжна и не будет меняться никогда на протяжении работы алгоритма - зачем ей быть переменной?) Добавлено спустя 1 минуту 7 секунд: но выше же ты ее используешь) $we = str_split($word);
да, я уже затестил, но отвлёкся на споры о мировоззрении в соседнем топике. Код (PHP): <?php $chars = ['a', 'b', 'x', '1']; $word = '1a'; if (empty($word)) { $pointers = [0]; } else { $we = preg_split('//u', $word, -1, PREG_SPLIT_NO_EMPTY); $we = array_reverse($we); //$pointers[0] - правый символ foreach ($we as $w) { foreach ($chars as $ck => $cv) { if ($w === $cv) { $pointers[] = $ck; } } } } $cmax = count($chars) - 1; for ($i = 0; $i < 10; $i++) { $pointers = iter($pointers, $cmax); echo buildWord($pointers, $chars), '<br>'; } function buildWord($pointers, $chars) { $word = ''; $pointers = array_reverse($pointers); foreach ($pointers as $p) { $word .= $chars[$p]; } return $word; } function iter($pointers, $cmax) { $pointers[0]++; reset($pointers); $flag = true; $index = 0; do { if ($pointers[$index] <= $cmax) { $flag = false; } else { $pointers[$index] = 0; if (!isset($pointers[$index + 1])) { $pointers[$index + 1] = 0; } else { $pointers[$index + 1]++; } } $index++; } while ($flag == true); return $pointers; }
Даже проги на компилируемых языках не могут нормально подобрать пароль больше восьми символов, что уж говорить про интерпретируемый PHP. У меня, например, была халтурка по подбору пароля к zip-файлу. Проц выдавал что-то около 30млн паролей в секунду. Благо я нашел программу, способную задействовать CUDA и чудовищную вычислительную мощь моей видюхи(GTX470, та ещё грелка), скорость подбора возрасла до 700млн. Полный перебор 8ми знаков(цифры, латинские буквы в верхнем и нижнем регистре) занимал около 4 дней непрерывной работы. Так что, думаю, шесть символов - предел для данного подхода
да, подобный вариант тоже пришел мне в голову. ибо сразу была видна аналогия простого увеличения числа в системе по кастомному основанию. с перебором определенных символов. типа как в шестнадцатиричной. но учитывая задачу ТСа, мне пришлось сделать две функции минимум(типа decToMybase() и mybaseToDec()), плюс цикл, плюс определение с какого начать(мы же не с нуля начинаем) и каким закончить... в общем моя реализация показалась слишком громоздкой. потому и пришел к другому варианту.
например возмем 16-тиричную систему счисления. принцип тотже, только другой набор симовлов. но у нас отличие в том, что набор и кол-во символов другое, и может вообще меняться. тоесть аналого системы счисления, но с произвольным основанием.
Это особый случай системы счисления — bijective projection. Числа "1", "01" и прочие "001" не равны. Там на stackoverflow, автор лучшего ответа дает ссылку на вики.