Hапечатать все перестановки чисел 1..N

ProGGGer

Новичок
Hапечатать все перестановки чисел 1..N

Собственно такая вот задача, по определенному набору символов надо найти все перестановки.
как пример дано 12 результат : 12 , 21
дано 123 результат : 123 , 132, 213 , 231, 312, 321
вообщем и так далее...
я составил алгоритм перестановки символов, но работает не совсем правильно.

PHP:
<?php
$flag =0;

function chek($str,$numSymbol)
{
    global  $flag;
    global $lengtchString;
    
    while ($flag != $numSymbol )
    {
        for ($i=0;$i<$lengtchString-1;$i++)
        {
            $temp = $str[$i]; 
            $str[$i] = $str[$i+1];
            $str[$i+1] = $temp;  
            echo $str."<br>";
            $xx++;
        }
        $flag++;
    }
echo "<br> Всего строк $xx";
}

$str =  "1234";
$lengtchString = strlen($str);
echo "длина строки $lengtchString <br><br>";
chek($str,$lengtchString);
?>
Для 3 дначений работает нормально. но для 4 выдает 12 комбинаций, хотя правильные 24 комбинации.

нашел в интернете пример реализиции, но непонимаю работу алгоритма.
пример реализации http://algolist.manual.ru/maths/combinat/permutations.php


Если кто делал на php отпишите какие мысли. Понимаю что при переборе из 10 символов получаеться очень долго и много комбинаций, но все будет сохраняться в файл.
 

dimagolov

Новичок
каждый из символов может быть на любой позиции. то есть делаешь массив с ключами символов и заполняешь его всеми возможными номерами позиций для каждого ключа.
потом цикл пока не пустой тот массив:
перебираешь все символы, берешь первую существующую позицию для каждого и смотришь не встречалась ли она уже, если встречалась - берешь другую, пока на найдешь ту, что не встречалась в текущем наборе (то есть нуже еще один массив текущего набора). Найденную позицию удаляешь из исходного массива. Как собрал все символы - вывел их из текущего набора последовательно.

-~{}~ 22.04.08 09:21:

вообще написал алгоритм для перестановки любого набора символов (правда без учета повторов если такие есть), для чисел может что-то умней можно придумать
 

Sluggard

Новичок
ProGGGer
Ф-я может быть и рекурсивной. Идея алгоритма следующая. Для строки длиной X каждый символ должен побывать на верху. У оставшихся символов снова находятся всевозможные варианты. Поэтому мы организовываем цикл по всем символам. В каждой итерации вытаскиваем i-й символ из строки, а для оставшихся снова вызываем нашу ф-ю, чтобы она сделала перебор строки длиной X-1. Т.о. ф-я должна получиться не больше 10-ти строк.

dimagolov
Не затратно?
 

ProGGGer

Новичок
Хорошо спаибо попробую сделать так как вы написали.
Получаеться что перестановка идет постоянно с строкой без первого символа, на второй иттерации уже без 2... и т.д...
 

dimagolov

Новичок
Sluggard, можем посчитать что более затратно - рекурсия или массивы, причем поиск по которым можем делать по хешам.

Для N cимволов у нас будет число перестоновок N!, причем для генерации каждой нужен будет рекурсивный стек глубиной N, то есть N*N! вызовов, для 10 цифр это 36288000.

для моего решения нужна начальная матрица N*N , которая с каждой итерацией будет терять N элементов.

-~{}~ 22.04.08 11:12:

хотя ИМХО для оценки быстродействия надо будет написать рабочие примеры и протестить их
 

rotoZOOM

ACM maniac
ProGGGer Ты еще не указал одно немаловажное условие, могут ли повторятся символы в наборе? При положительном ответе на этот вопрос алгоритм Sluggard отлично работает, но только перед запуском необходимо отсортировать символы в наборе и при подстановке следующего символа в конечную строку, смотреть, чтобы он не был равен предыдущему.
Рекурсией (по крайней мере для меня) реализовать это легче, но существует и аналог рекурсивного алгоритма, реализованный в STL'ном next_permutation, где не используется рекурсия.
 

Sluggard

Новичок
то есть N*N! вызовов
Не трезвый вывод. С какого бадуна ты их перемножаешь, чтобы узнать количество вызовов?

Откровенно, твой алгоритм я не просек.
>> Найденную позицию удаляешь из исходного массива.
Каждый символ может присутствовать в той же позиции (N-1)! раз. В любом случае, мы должны получить N! строк. Каким образом ты хочешь уменьшить количество итераций и затраты вообще, привлекая работу с массивами??
 

dimagolov

Новичок
>> Каждый символ может присутствовать в той же позиции (N-1)! раз. В любом случае, мы должны получить N! строк.
Sluggard, похоже на то что я действительно протупил :(
 

dimagolov

Новичок
LONGMAN, ты не нашел реализации на PHP, а не алгоритма. Сравнив реализации, скажем на C# и C++ легко понять в чем суть алгоритма даже без знания этих ЯП.
 

LONGMAN

Dark Side of the Moon..
dimagolov
Да, точно, не нашёл реализации.. Посмотрю алгоритм на C++ и попытаюсь сделать всё это на php

-~{}~ 15.04.09 04:47:

В этих алгоритмах нету вывода всех перестановок :( Есть только следующий, k-ую и вывод номер перестановки.. Случайно ни у кого нет готовое решение для моей задачи?
 

dimagolov

Новичок
KthPermutation дает перестановку по ее номеру, все что надо - это цикл по числу перестановок, то есть от 1 до N! (если не учитывать повторяющиеся буквы)
 

LONGMAN

Dark Side of the Moon..
dimagolov
Какая функция эквивалентно С-шнему a.setbounds в php?
 

AmdY

Пью пиво
Команда форума
по первой же ссылке в гугле нашёл сразу две реализации на сях и на паскале.
советую искать в гугле, но не алгоритм, а другие сферы работ не связанные с программированием. насколько я помню в моей сельской школе это было в программе 9-го класса по информатике.
LONGMAN
да, я - мудак, но это не сделает из тебя программиста.
 

LONGMAN

Dark Side of the Moon..
AmdY
То о чём мы говорим задача не так тривиальная как кажется. Хорошенко загуглил и увидел что на php до сих пор нет готовой решении. Это ни о чём не говорит? Или я плохо искал?
 

LONGMAN

Dark Side of the Moon..
dimagolov
Я люблю программирование, очен люблю.. И умею. Может я не мега-кодер, но всё же умею.. Видима дело в ленивости или в не знание тонкости русского языка.. И вы и гугл неадекватно меня понимаете.

-~{}~ 15.04.09 18:20:

Подскажите пожалуйста за что отвечает функция a.setbounds в C++
 

dimagolov

Новичок
LONGMAN, нету в C++ такой ф-ии, это метод класса, объектом которого является a. Поэтому я и сказал, сравни реализации на нескольких языках, так как они будут различаться на языковые особенности, но совпадать по алгоритму. По идее подход в C# должен быть ближе к PHP, чем в C++.
 
Сверху