Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Перестановки алфавита без рекурсии. Без массивов. PHP

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (1): [1]   

> Описание: перестановки php permutations
dcc0
Отправлено: 06 Сентября, 2014 - 17:05:11
Post Id


Участник


Покинул форум
Сообщений всего: 1043
Дата рег-ции: Июль 2014  


Помог: 10 раз(а)




Ребята, если кому-то будет интересна эта тема, вот мои наработки.
Пока, вроде, получилось. Правда, есть ограничение на генерируемые размещения.
Собственно, заметка о том, как превратить размещения в перестановки.

Все алгоритмы, которые я встречал в Интернете на ключевые слова "перестановки и permutations" мне показались сложными для понимания. Заодно отталкивает использование рекурсии. Работая над другим скриптом, пришел к следующему выводу.
Чтобы получить все перестановки, которые, как известно, равны факториалу n!,
сначала надо получить все размещения с повторениями. Мной был найден такой скрипт и несколько переделан, взят с hashcode, автора не помню.
Мы генерируем все размещения в данном случае 4-х элементов - abcd. Для этого используется цикл до 4 в степени 4 (все размещения с повторением). Данные преобразуются в четверичную систему, дописываются нули слева. Затем с помощью strtr преобразование в abcd. Вот, с первым скриптом все.

PHP:
скопировать код в буфер обмена
  1. <?PHP
  2. /*Cоздать файл с набором алфавита. Исходный скрипта взят с hashcode*/
  3.  $handle = fopen("f.txt", "w");
  4. $a=-1;
  5. while(++$a<256) {
  6.    $c=str_pad(base_convert($a, 10, 4), 4, "0", STR_PAD_LEFT);
  7.  $b=strtr($c, "0123", "abcd");
  8. fwrite($handle, "$b\r\n");      
  9. }
  10.  fclose($handle);
  11.  ?>
  12.  


А дальше?! Надо удалить из всех размещений каждую строку, в который символ повторяется. Второй скрипт читает из файла f.txt построчно, проверяет количество одного символа в строке и записывает в промежуточный файл только те строки, в которых символ один. Когда цикл переберет все записи на одну букву, подставит другую. Первый цикл - перебора массива - будет иметь столько итераций, сколько всего букв в алфавите, т.е. n. Иначе говоря, есть abcd - 4 буквы, у цикла перебора массива будет 4 итерации.
Промежуточные вычисления записываются в дополнительный файлы, потом файлы удаляются и переименовываются.

PHP:
скопировать код в буфер обмена
  1.  
  2. <?PHP
  3. /*Входной алфавит*/
  4.  $arr = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h');
  5.  
  6. /*Количество символов*/
  7. $n=3;
  8. /*Перебор. Сброс на последнем символе*/
  9. foreach($arr as $k => $v) {
  10.     if($k==$n) {
  11.   break;
  12.  }
  13.  $handle = fopen("f.txt", "r");
  14.     $handl1 = fopen("f1.txt", "w");
  15.  /*Читаем из файла по строчно*/        
  16. while (!feof($handle)) {
  17.   $buffer = fgets($handle);
  18.  
  19.    /*Если символ встречается 1 раз пишем в другой файл. Переменная - шаблон
  20.    подставляется из цикла сверху*/     
  21. $c = preg_match_all("/$v{1}/",  $buffer, $out);
  22. if($c==1) {
  23. fwrite($handl1, "$buffer");
  24.  }
  25. }
  26.  fclose($handle);
  27. fclose($handl1);
  28. /*Переименовываем все файлы, удалем промежуточные*/
  29.  rename("f.txt", "old1_f.txt");
  30.   unlink ("old1_f.txt");
  31. rename("f1.txt", "f.txt");
  32. }
  33. $c=file('f.txt');
  34. print_r($c);
  35. ?>
  36.  

(Отредактировано автором: 09 Июня, 2015 - 11:43:26)



-----
Март 2021. Бросил программирование
 
 Top
dcc0
Отправлено: 07 Сентября, 2014 - 19:35:06
Post Id


Участник


Покинул форум
Сообщений всего: 1043
Дата рег-ции: Июль 2014  


Помог: 10 раз(а)




Еще такой вариант получения перестановок, полуавтоматический. Не знаю, где может пригодиться. Идея такая: можно генерировать любой набор букв рандомно.
Например, при помощи скрипта из этой статьи: http://www.php.su/articles/?cat=...les&page=052
Писать этот набор в файл, другим скриптом отсеивать все строчки, в которых 1 буква встречается более одного раза, а затем применять arrar_unique для поиска уникальных.

Таким образом поиск будет постепенным.

Спойлер (Отобразить)


Спойлер (Отобразить)


-----
Март 2021. Бросил программирование
 
 Top
nkl
Отправлено: 08 Сентября, 2014 - 10:40:31
Post Id



Посетитель


Покинул форум
Сообщений всего: 305
Дата рег-ции: Янв. 2012  


Помог: 1 раз(а)




Это для чего вообще? Не понял
 
 Top
Tyoma5891
Отправлено: 08 Сентября, 2014 - 11:02:33
Post Id


Частый посетитель


Покинул форум
Сообщений всего: 621
Дата рег-ции: Авг. 2013  


Помог: 5 раз(а)




nkl пишет:
Это для чего вообще? Не понял

у меня такое подозрение, для побора паролей, но для этого достаточно тупого перебора методом +1 )
 
 Top
dcc0
Отправлено: 08 Сентября, 2014 - 11:09:13
Post Id


Участник


Покинул форум
Сообщений всего: 1043
Дата рег-ции: Июль 2014  


Помог: 10 раз(а)




nkl, практического применения пока не вижу, но интересны способы получения всех перестановок алфавита, например, abcd или ab02 или a+?& и т.д.

Наиболее оптимальным считается рекурсивный алгоритм.
Пример 1:
http://stackoverflow[dot]com/questio[dot][dot][dot]tations-in-a-set
Пример 2: http://tvolf[dot]blogspot[dot]ru/2013/09/php[dot]html
С хорошим объяснением.
Но для понимания довольно сложен (мое мнение). Рекурсивный будет работать с символами до 10, потом просто не хватит памяти (хотя тут зависит от машины и настроек).

Второй вариант без рекурсии, где сначала надо найти все размещения с повторениями, сгенерирует до 7 включительно, так как понятно разм. с повторениями намного больше.
Пример, если всех перестановок семи элементов abcdefg - 7! = 5040, то размещений 7⁷ = 823543. Т.е. вариант долгий и нудный, но он есть.

Вариант третий можно автоматизировать, он совсем долгий (почти бесконечный Улыбка) Один скрипт генерирует n-ое количество случайных выборок и сохраняет в файл, другой скрипт забирает результат удаляет то - что не попадает под перестановку, например aaabc, потом удаляет повторы, опять же можно сохранять в другой файл, который будет базой

Третий скрипт находит все перестановки 4 эл. за 100 рекурсивных вызовов.
(Добавление)
Tyoma5891 пишет:

у меня такое подозрение, для побора паролей, но для этого достаточно тупого перебора методом +1 )

Причем тут перестановки и перебор? При перестановках вы не получаете перебора всех значений.
Третий вариант интересен тем, что последовательность перестановок будет случайной.

(Отредактировано автором: 08 Сентября, 2014 - 14:37:15)



-----
Март 2021. Бросил программирование
 
 Top
Страниц (1): [1]
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Хранение данных, их вывод и обработка »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB