Algorithme pour générer toutes les permutations d'une liste?

dites que j'ai une liste de N éléments, je sais qu'il n'y en a pas! des façons possibles d'ordonner ces éléments. Qu'est-ce qu'un algorithme pour générer toutes les commandes possibles de cette liste? Exemple, j'ai la liste [a, b, c]. L'algorithme de retour [[a, b, c], [a, c, b], [b, a, c], [b, c, a], [c, a, b], [c, b, a]].

je lis ceci ici http://en.wikipedia.org/wiki/Permutation#Algorithms_to_generate_permutations

Mais Wikipedia n'a jamais été bon d'expliquer. Je ne comprends pas grand-chose.

109
demandé sur Jon Seigel 2010-04-26 05:52:19

30 réponses

fondamentalement, pour chaque élément de gauche à droite, toutes les permutations des éléments restants sont générées (et chacune est ajoutée avec les éléments courants). Cela peut être fait de façon récursive (ou itérative si vous aimez la douleur) jusqu'à ce que le dernier point est atteint, auquel point il n'y a qu'un ordre possible.

donc avec la liste [1,2,3,4] toutes les permutations qui commencent par 1 sont générées, puis toutes les permutations qui commencent par 2, puis 3 puis 4.

cela réduit effectivement le problème de trouver des permutations d'une liste de quatre articles à une liste de trois articles. Après avoir réduit à 2 et puis 1 listes d'articles, tous seront trouvés.

Exemple montrant les permutations du procédé à l'aide de 3 billes de couleur:

Red, green and blue coloured balls ordered permutations image (de https://en.wikipedia.org/wiki/Permutation#/media/File:Permutations_RGB.svg - https://commons.wikimedia.org/wiki/File:Permutations_RGB.svg )

89
répondu WhirlWind 2016-09-28 15:46:52

voici un algorithme en Python qui fonctionne en place sur un tableau:

def permute(xs, low=0):
    if low + 1 >= len(xs):
        yield xs
    else:
        for p in permute(xs, low + 1):
            yield p        
        for i in range(low + 1, len(xs)):        
            xs[low], xs[i] = xs[i], xs[low]
            for p in permute(xs, low + 1):
                yield p        
            xs[low], xs[i] = xs[i], xs[low]

for p in permute([1, 2, 3, 4]):
    print p

vous pouvez essayer le code pour vous-même ici: http://repl.it/J9v

24
répondu cdiggins 2013-07-06 14:47:38

la réponse de Wikipedia pour "ordre lexicographique" me semble parfaitement explicite dans le style du livre de cuisine. Il cite une origine du XIVe siècle pour l'algorithme!

je viens d'écrire une implémentation rapide en Java de L'algorithme de Wikipédia comme une vérification et ce n'était pas un problème. Mais ce que vous avez dans votre Q comme exemple N'est pas "list all permutations", mais "a LIST of all permutations", donc wikipedia ne sera pas beaucoup d'aide pour vous. Vous avez besoin d'une langue dans laquelle les listes de permutations sont facilement construits. Et croyez-moi, les listes de quelques milliards de long ne sont généralement pas traitées dans des langues impératives. Vous voulez vraiment un langage de programmation fonctionnel non-strict, dans lequel les listes sont un objet de première classe, pour sortir des trucs tout en n'amenant pas la machine près de la mort de chaleur de l'univers.

c'est facile. En Haskell standard ou tout autre langage FP moderne:

-- perms of a list
perms :: [a] -> [ [a] ]
perms (a:as) = [bs ++ a:cs | perm <- perms as, (bs,cs) <- splits perm]
perms []     = [ [] ]

et

-- ways of splitting a list into two parts
splits :: [a] -> [ ([a],[a]) ]
splits []     = [ ([],[]) ]
splits (a:as) = ([],a:as) : [(a:bs,cs) | (bs,cs) <- splits as]
13
répondu Peter Breuer 2016-11-03 11:08:37

il y a déjà beaucoup de bonnes solutions ici, mais je voudrais partager comment j'ai résolu ce problème sur mon propre et j'espère que cela pourrait être utile pour quelqu'un qui voudrait également dériver sa propre solution.

après quelques réflexions sur le problème, je suis arrivé à deux conclusions:

  1. pour la liste L de taille n il y aura un nombre égal de solutions commençant par l 1 , L 2 ... L n éléments de la liste. Puisqu'au total il y a des permutations n! de la liste de taille n , nous obtenons des permutations n! / n = (n-1)! dans chaque groupe.
  2. la liste des 2 éléments n'a que 2 permutations = > [a,b] et [b,a] .

en utilisant ces deux idées simples, j'ai dérivé l'algorithme suivant:

permute array
    if array is of size 2
       return first and second element as new array
       return second and first element as new array
    else
        for each element in array
            new subarray = array with excluded element
            return element + permute subarray

Voici comment je l'ai mis en œuvre dans C#:

public IEnumerable<List<T>> Permutate<T>(List<T> input)
{
    if (input.Count == 2) // this are permutations of array of size 2
    {
        yield return new List<T>(input);
        yield return new List<T> {input[1], input[0]}; 
    }
    else
    {
        foreach(T elem in input) // going through array
        {
            var rlist = new List<T>(input); // creating subarray = array
            rlist.Remove(elem); // removing element
            foreach(List<T> retlist in Permutate(rlist))
            {
                retlist.Insert(0,elem); // inserting the element at pos 0
                yield return retlist;
            }

        }
    }
}
12
répondu Alexander Galkin 2014-05-18 20:45:31

comme disait WhirlWind, vous commencez au début.

vous changez le curseur avec chaque valeur restante, y compris le curseur lui-même, ce sont tous de nouvelles instances (j'ai utilisé un int[] et array.clone() dans l'exemple).

effectue alors des permutations sur toutes ces différentes listes, en s'assurant que le curseur est à droite.

quand il n'y a plus de valeurs restantes (le curseur est à la fin), imprimez la liste. C'est l'arrêt condition.

public void permutate(int[] list, int pointer) {
    if (pointer == list.length) {
        //stop-condition: print or process number
        return;
    }
    for (int i = pointer; i < list.length; i++) {
        int[] permutation = (int[])list.clone();.
        permutation[pointer] = list[i];
        permutation[i] = list[pointer];
        permutate(permutation, pointer + 1);
    }
}
9
répondu dinadineke 2013-04-30 21:16:36

récursif prend toujours un certain effort mental pour maintenir. Et pour les grands nombres, factoriel est facilement énorme et le débordement de la pile sera facilement un problème.

pour les petits nombres (3 ou 4, ce qui est le plus souvent rencontré), les boucles multiples sont très simples et simples. Il est regrettable réponses avec des boucles avais pas voté.

commençons par l'énumération (plutôt que la permutation). Il suffit de lire le code sous forme de pseudo-code perl.

$foreach $i1 in @list
    $foreach $i2 in @list 
        $foreach $i3 in @list
            print "$i1, $i2, $i3\n"

énumération est plus souvent rencontré que la permutation, mais si la permutation est nécessaire, il suffit d'ajouter les conditions:

$foreach $i1 in @list
    $foreach $i2 in @list 
        $if $i2==$i1
            next
        $foreach $i3 in @list
            $if $i3==$i1 or $i3==$i2
                next
            print "$i1, $i2, $i3\n"

maintenant si vous avez vraiment besoin de méthode générale potentiellement pour les grandes listes, nous pouvons utiliser la méthode radix. Tout d'abord, considérer le problème d'énumération:

$n=@list
my @radix
$for $i=0:$n
    $radix[$i]=0
$while 1
    my @temp
    $for $i=0:$n
        push @temp, $list[$radix[$i]]
    print join(", ", @temp), "\n"
    $call radix_increment

subcode: radix_increment
    $i=0
    $while 1
        $radix[$i]++
        $if $radix[$i]==$n
            $radix[$i]=0
            $i++
        $else
            last
    $if $i>=$n
        last

incrément Radix est essentiellement le comptage de nombres (à la base du nombre d'éléments de liste).

maintenant si vous avez besoin de permutaion, il suffit d'ajouter les vérifications à l'intérieur de la boucle:

subcode: check_permutation
    my @check
    my $flag_dup=0
    $for $i=0:$n
        $check[$radix[$i]]++
        $if $check[$radix[$i]]>1
            $flag_dup=1
            last
    $if $flag_dup
        next

Edit: le code ci-dessus devrait fonctionner, mais pour la permutation, radix_ incrément pourrait être inutile. Ainsi, si le temps est une préoccupation pratique, nous devons changer l'augmentation de la radioactivité en permute_inc:

subcode: permute_init
    $for $i=0:$n
        $radix[$i]=$i

subcode: permute_inc                                       
    $max=-1                                                
    $for $i=$n:0                                           
        $if $max<$radix[$i]                                
            $max=$radix[$i]                                
        $else                                              
            $for $j=$n:0                                   
                $if $radix[$j]>$radix[$i]                  
                    $call swap, $radix[$i], $radix[$j]     
                    break                                  
            $j=$i+1                                        
            $k=$n-1                                        
            $while $j<$k                                   
                $call swap, $radix[$j], $radix[$k]         
                $j++                                       
                $k--                                       
            break                                          
    $if $i<0                                               
        break                                              

bien sûr maintenant ce code est logiquement plus complexe, je vais partir pour l'exercice du lecteur.

7
répondu Hui Zhou 2014-06-25 13:14:13

si quelqu'un se demande comment faire en permutation en javascript.

Idée/pseudo-code

  1. choisir un élément à la fois
  2. permuter reste de l'élément, puis ajouter l'élément choisi pour l'ensemble de la permutation

par exemple. 'a'+ permuter(colombie-britannique). permute of bc serait bc & cb. Maintenant, ajoutez ces deux - là et vous obtiendrez abc, acb. de même, choisir B + permute (ac) province bac, bca...et de continuer.

regardez maintenant le code

function permutations(arr){

   var len = arr.length, 
       perms = [],
       rest,
       picked,
       restPerms,
       next;

    //for one or less item there is only one permutation 
    if (len <= 1)
        return [arr];

    for (var i=0; i<len; i++)
    {
        //copy original array to avoid changing it while picking elements
        rest = Object.create(arr);

        //splice removed element change array original array(copied array)
        //[1,2,3,4].splice(2,1) will return [3] and remaining array = [1,2,4]
        picked = rest.splice(i, 1);

        //get the permutation of the rest of the elements
        restPerms = permutations(rest);

       // Now concat like a+permute(bc) for each
       for (var j=0; j<restPerms.length; j++)
       {
           next = picked.concat(restPerms[j]);
           perms.push(next);
       }
    }

   return perms;
}

Prenez votre temps pour comprendre cela. J'ai eu ce code de ( pertumation en JavaScript )

4
répondu KhanSharp 2014-01-12 15:51:11

un autre en Python, il n'est pas en place comme @cdiggins, mais je pense que c'est plus facile à comprendre""

def permute(num):
    if len(num) == 2:
        # get the permutations of the last 2 numbers by swapping them
        yield num
        num[0], num[1] = num[1], num[0]
        yield num
    else:
        for i in range(0, len(num)):
            # fix the first number and get the permutations of the rest of numbers
            for perm in permute(num[0:i] + num[i+1:len(num)]):
                yield [num[i]] + perm

for p in permute([1, 2, 3, 4]):
    print p
3
répondu zhywu 2014-02-23 22:46:47

je pensais écrire un code pour obtenir les permutations de n'importe quel entier donné de n'importe quelle taille, c.-à-d., fournir un nombre 4567 nous obtenons toutes les permutations possibles jusqu'à 7654...alors j'ai travaillé dessus et j'ai trouvé un algorithme et finalement l'ai mis en œuvre, voici le code écrit en"c". Vous pouvez simplement le copier et l'exécuter sur n'importe quel compilateur open source. Mais quelques défauts sont en attente d'être débogué. Veuillez apprécier.

Code:

#include <stdio.h>
#include <conio.h>
#include <malloc.h>

                //PROTOTYPES

int fact(int);                  //For finding the factorial
void swap(int*,int*);           //Swapping 2 given numbers
void sort(int*,int);            //Sorting the list from the specified path
int imax(int*,int,int);         //Finding the value of imax
int jsmall(int*,int);           //Gives position of element greater than ith but smaller than rest (ahead of imax)
void perm();                    //All the important tasks are done in this function


int n;                         //Global variable for input OR number of digits

void main()
{
int c=0;

printf("Enter the number : ");
scanf("%d",&c);
perm(c);
getch();
}

void perm(int c){
int *p;                     //Pointer for allocating separate memory to every single entered digit like arrays
int i, d;               
int sum=0;
int j, k;
long f;

n = 0;

while(c != 0)               //this one is for calculating the number of digits in the entered number
{
    sum = (sum * 10) + (c % 10);
    n++;                            //as i told at the start of loop
    c = c / 10;
}

f = fact(n);                        //It gives the factorial value of any number

p = (int*) malloc(n*sizeof(int));                //Dynamically allocation of array of n elements

for(i=0; sum != 0 ; i++)
{
    *(p+i) = sum % 10;                               //Giving values in dynamic array like 1234....n separately
    sum = sum / 10;
}

sort(p,-1);                                         //For sorting the dynamic array "p"

for(c=0 ; c<f/2 ; c++) {                        //Most important loop which prints 2 numbers per loop, so it goes upto 1/2 of fact(n)

    for(k=0 ; k<n ; k++)
        printf("%d",p[k]);                       //Loop for printing one of permutations
    printf("\n");

    i = d = 0;
    i = imax(p,i,d);                            //provides the max i as per algo (i am restricted to this only)
    j = i;
    j = jsmall(p,j);                            //provides smallest i val as per algo
    swap(&p[i],&p[j]);

    for(k=0 ; k<n ; k++)
        printf("%d",p[k]);
    printf("\n");

    i = d = 0;
    i = imax(p,i,d);
    j = i;
    j = jsmall(p,j);
    swap(&p[i],&p[j]);

    sort(p,i);
}
free(p);                                        //Deallocating memory
}

int fact (int a)
{
long f=1;
while(a!=0)
{
    f = f*a;
    a--;
}
return f;
}


void swap(int *p1,int *p2)
{
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
return;
}


void sort(int*p,int t)
{
int i,temp,j;
for(i=t+1 ; i<n-1 ; i++)
{
    for(j=i+1 ; j<n ; j++)
    {
        if(*(p+i) > *(p+j))
        {
            temp = *(p+i);
            *(p+i) = *(p+j);
            *(p+j) = temp;
        }
    }
}
}


int imax(int *p, int i , int d)
{
    while(i<n-1 && d<n-1)
{
    if(*(p+d) < *(p+d+1))
    {   
        i = d;
        d++;
    }
    else
        d++;
}
return i;
}


int jsmall(int *p, int j)
{
int i,small = 32767,k = j;
for (i=j+1 ; i<n ; i++)
{
    if (p[i]<small && p[i]>p[k])
    {     
       small = p[i];
       j = i;
    }
}
return j;
}
3
répondu FreakPirate 2014-02-27 18:07:50
void permutate(char[] x, int i, int n){
    x=x.clone();
    if (i==n){
        System.out.print(x);
        System.out.print(" ");
        counter++;}
    else
    {
        for (int j=i; j<=n;j++){
     //   System.out.print(temp); System.out.print(" ");    //Debugger
        swap (x,i,j);
      //  System.out.print(temp); System.out.print(" "+"i="+i+" j="+j+"\n");// Debugger
        permutate(x,i+1,n);
    //    swap (temp,i,j);
    }
    }
}

void swap (char[] x, int a, int b){
char temp = x[a];
x[a]=x[b];
x[b]=temp;
}

j'ai créé celui-ci. basé sur des recherches trop permuter(qwe, 0, qwe.longueur-1); Juste pour que vous le sachiez, vous pouvez le faire avec ou sans backtrack

3
répondu Luigi Mackenzie C. Brito 2014-02-28 02:51:29

Voici une méthode de rubis jouet qui fonctionne comme #permutation.to_a qui pourrait être plus lisible pour les fous. C'est hella lent, mais aussi 5 lignes.

def permute(ary)
  return [ary] if ary.size <= 1
  ary.collect_concat.with_index do |e, i|
    rest = ary.dup.tap {|a| a.delete_at(i) }
    permute(rest).collect {|a| a.unshift(e) }
  end
end
3
répondu Jenner LaFave 2014-09-25 07:51:10

j'ai écrit Cette solution récursive dans ANSI C. Chaque exécution de la fonction Permutate fournit une permutation différente jusqu'à ce que tout soit terminé. Les variables globales peuvent également être utilisées pour les variables fact et count.

#include <stdio.h>
#define SIZE 4

void Rotate(int vec[], int size)
{
    int i, j, first;

    first = vec[0];
    for(j = 0, i = 1; i < size; i++, j++)
    {
        vec[j] = vec[i];
    }
    vec[j] = first;
}

int Permutate(int *start, int size, int *count)
{
    static int fact;

    if(size > 1)
    {
        if(Permutate(start + 1, size - 1, count))
        {
            Rotate(start, size);
        }
        fact *= size;
    }
    else
    {
        (*count)++;
        fact = 1;
    }

    return !(*count % fact);
}

void Show(int vec[], int size)
{
    int i;

    printf("%d", vec[0]);
    for(i = 1; i < size; i++)
    {
        printf(" %d", vec[i]);
    }
    putchar('\n');
}

int main()
{
    int vec[] = { 1, 2, 3, 4, 5, 6 }; /* Only the first SIZE items will be permutated */
    int count = 0;

    do
    {
        Show(vec, SIZE);
    } while(!Permutate(vec, SIZE, &count));

    putchar('\n');
    Show(vec, SIZE);
    printf("\nCount: %d\n\n", count);

    return 0;
}
3
répondu Horacio 2015-06-08 13:29:10

version Java

/**
 * @param uniqueList
 * @param permutationSize
 * @param permutation
 * @param only            Only show the permutation of permutationSize,
 *                        else show all permutation of less than or equal to permutationSize.
 */
public static void my_permutationOf(List<Integer> uniqueList, int permutationSize, List<Integer> permutation, boolean only) {
    if (permutation == null) {
        assert 0 < permutationSize && permutationSize <= uniqueList.size();
        permutation = new ArrayList<>(permutationSize);
        if (!only) {
            System.out.println(Arrays.toString(permutation.toArray()));
        }
    }
    for (int i : uniqueList) {
        if (permutation.contains(i)) {
            continue;
        }
        permutation.add(i);
        if (!only) {
            System.out.println(Arrays.toString(permutation.toArray()));
        } else if (permutation.size() == permutationSize) {
            System.out.println(Arrays.toString(permutation.toArray()));
        }
        if (permutation.size() < permutationSize) {
            my_permutationOf(uniqueList, permutationSize, permutation, only);
        }
        permutation.remove(permutation.size() - 1);
    }
}

E. G.

public static void main(String[] args) throws Exception { 
    my_permutationOf(new ArrayList<Integer>() {
        {
            add(1);
            add(2);
            add(3);

        }
    }, 3, null, true);
}

sortie:

  [1, 2, 3]
  [1, 3, 2]
  [2, 1, 3]
  [2, 3, 1]
  [3, 1, 2]
  [3, 2, 1]
3
répondu Bruce Zu 2016-01-31 02:04:49

en PHP

$set=array('A','B','C','D');

function permutate($set) {
    $b=array();
    foreach($set as $key=>$value) {
        if(count($set)==1) {
            $b[]=$set[$key];
        }
        else {
            $subset=$set;
            unset($subset[$key]);
            $x=permutate($subset);
            foreach($x as $key1=>$value1) {
                $b[]=$value.' '.$value1;
            }
        }
    }
    return $b;
}

$x=permutate($set);
var_export($x);
3
répondu nerdface 2016-04-18 16:07:06

enter image description here

// C program to print all permutations with duplicates allowed
#include <stdio.h>
#include <string.h>

/* Function to swap values at two pointers */
void swap(char *x, char *y)
{
    char temp;
    temp = *x;
    *x = *y;
    *y = temp;
}

/* Function to print permutations of string
   This function takes three parameters:
   1. String
   2. Starting index of the string
   3. Ending index of the string. */

void permute(char *a, int l, int r)
{
   int i;
   if (l == r)
     printf("%s\n", a);
   else
   {
       for (i = l; i <= r; i++)
       {
          swap((a+l), (a+i));
          permute(a, l+1, r);
          swap((a+l), (a+i)); //backtrack
       }
   }
}

/* Driver program to test above functions */
int main()
{
    char str[] = "ABC";
    int n = strlen(str);
    permute(str, 0, n-1);
    return 0;
}

Référence: Geeksforgeeks.org

3
répondu Sazzad Hissain Khan 2017-06-13 04:15:43

Voici le code en Python pour imprimer toutes les permutations possibles d'une liste:

def next_perm(arr):
    # Find non-increasing suffix
    i = len(arr) - 1
    while i > 0 and arr[i - 1] >= arr[i]:
        i -= 1
    if i <= 0:
        return False

    # Find successor to pivot
    j = len(arr) - 1
    while arr[j] <= arr[i - 1]:
        j -= 1
    arr[i - 1], arr[j] = arr[j], arr[i - 1]

    # Reverse suffix
    arr[i : ] = arr[len(arr) - 1 : i - 1 : -1]
    print arr
    return True

def all_perm(arr):
    a = next_perm(arr)
    while a:
        a = next_perm(arr)
    arr = raw_input()
    arr.split(' ')
    arr = map(int, arr)
    arr.sort()
    print arr
    all_perm(arr)

j'ai utilisé un algorithme d'ordre lexicographique pour obtenir toutes les permutations possibles, mais un algorithme récursif est plus efficace. Vous pouvez trouver le code pour l'algorithme récursif ici: permutations de récursion Python

3
répondu Anuj Mittal 2017-06-28 14:58:29
public class PermutationGenerator
{
    private LinkedList<List<int>> _permutationsList;
    public void FindPermutations(List<int> list, int permutationLength)
    {
        _permutationsList = new LinkedList<List<int>>();
        foreach(var value in list)
        {
            CreatePermutations(value, permutationLength);
        }
    }

    private void CreatePermutations(int value, int permutationLength)
    {
        var node = _permutationsList.First;
        var last = _permutationsList.Last;
        while (node != null)
        {
            if (node.Value.Count < permutationLength)
            {
                GeneratePermutations(node.Value, value, permutationLength);
            }
            if (node == last)
            {
                break;
            }
            node = node.Next;
        }

        List<int> permutation = new List<int>();
        permutation.Add(value);
        _permutationsList.AddLast(permutation);
    }

    private void GeneratePermutations(List<int> permutation, int value, int permutationLength)
    {
       if (permutation.Count < permutationLength)
        {
            List<int> copyOfInitialPermutation = new List<int>(permutation);
            copyOfInitialPermutation.Add(value);
            _permutationsList.AddLast(copyOfInitialPermutation);
            List<int> copyOfPermutation = new List<int>();
            copyOfPermutation.AddRange(copyOfInitialPermutation);
            int lastIndex = copyOfInitialPermutation.Count - 1;
            for (int i = lastIndex;i > 0;i--)
            {
                int temp = copyOfPermutation[i - 1];
                copyOfPermutation[i - 1] = copyOfPermutation[i];
                copyOfPermutation[i] = temp;

                List<int> perm = new List<int>();
                perm.AddRange(copyOfPermutation);
                _permutationsList.AddLast(perm);
            }
        }
    }

    public void PrintPermutations(int permutationLength)
    {
        int count = _permutationsList.Where(perm => perm.Count() == permutationLength).Count();
        Console.WriteLine("The number of permutations is " + count);
    }
}
3
répondu Bahruz Balabayov 2017-12-17 13:43:48

Scala

    def permutazione(n: List[Int]): List[List[Int]] = permutationeAcc(n, Nil)



def permutationeAcc(n: List[Int], acc: List[Int]): List[List[Int]] = {

    var result: List[List[Int]] = Nil
    for (i ← n if (!(acc contains (i))))
        if (acc.size == n.size-1)
            result = (i :: acc) :: result
        else
            result = result ::: permutationeAcc(n, i :: acc)
    result
}
2
répondu Marco 2013-10-21 07:25:50

ceci est une version java pour la permutation

public class Permutation {

    static void permute(String str) {
        permute(str.toCharArray(), 0, str.length());
    }

    static void permute(char [] str, int low, int high) {
        if (low == high) {
            System.out.println(str);
            return;
        }

        for (int i=low; i<high; i++) {
            swap(str, i, low);
            permute(str, low+1, high);
            swap(str, low, i);
        }

    }

    static void swap(char [] array, int i, int j) {
        char t = array[i];
        array[i] = array[j];
        array[j] = t;
    }
}
2
répondu 杨小勇 2016-08-20 11:11:52

Voici une implémentation pour ColdFusion (nécessite CF10 en raison de L'argument de fusion à ArrayAppend ()):

public array function permutateArray(arr){

    if (not isArray(arguments.arr) ) {
        return ['The ARR argument passed to the permutateArray function is not of type array.'];    
    }

    var len = arrayLen(arguments.arr);
    var perms = [];
    var rest = [];
    var restPerms = [];
    var rpLen = 0;
    var next = [];

    //for one or less item there is only one permutation 
    if (len <= 1) {
        return arguments.arr;
    }

    for (var i=1; i <= len; i++) {
        // copy the original array so as not to change it and then remove the picked (current) element
        rest = arraySlice(arguments.arr, 1);
        arrayDeleteAt(rest, i);

         // recursively get the permutation of the rest of the elements
         restPerms = permutateArray(rest);
         rpLen = arrayLen(restPerms);

        // Now concat each permutation to the current (picked) array, and append the concatenated array to the end result
        for (var j=1; j <= rpLen; j++) {
            // for each array returned, we need to make a fresh copy of the picked(current) element array so as to not change the original array
            next = arraySlice(arguments.arr, i, 1);
            arrayAppend(next, restPerms[j], true);
            arrayAppend(perms, next);
        }
     }

    return perms;
}

basé sur la solution JS de KhanSharp ci-dessus.

2
répondu earachefl 2017-02-15 14:43:35

je sais que c'est un très vieux et même hors-sujet dans stackoverflow d'aujourd'hui, mais je voulais quand même apporter une réponse JavaScript amical pour la simple raison qu'il fonctionne dans votre navigateur.

j'ai aussi ajouté le point de rupture de la directive debugger pour que vous puissiez parcourir le code (chrome requis) pour voir comment cet algorithme fonctionne. Ouvrez votre console de développement dans chrome ( F12 dans windows ou CMD + OPTION + I sur mac) et cliquez sur"Exécuter code snippet". Ce implémente exactement le même algorithme que @Tourbillon présenté dans sa réponse.

votre navigateur devrait mettre en pause l'exécution de la directive debugger . Utilisez F8 pour continuer l'exécution du code.

parcourez le code et voyez comment il fonctionne!

function permute(rest, prefix = []) {
  if (rest.length === 0) {
    return [prefix];
  }
  return (rest
    .map((x, index) => {
      const oldRest = rest;
      const oldPrefix = prefix;
      // the `...` destructures the array into single values flattening it
      const newRest = [...rest.slice(0, index), ...rest.slice(index + 1)];
      const newPrefix = [...prefix, x];
      debugger;

      const result = permute(newRest, newPrefix);
      return result;
    })
    // this step flattens the array of arrays returned by calling permute
    .reduce((flattened, arr) => [...flattened, ...arr], [])
  );
}
console.log(permute([1, 2, 3]));
1
répondu Rico Kahler 2017-05-23 22:54:59

dans la solution Java suivante, nous profitons du fait que les chaînes sont immuables afin d'éviter de cloner le résultat à chaque itération.

l'entrée sera une chaîne, dites "abc", et la sortie sera toutes les permutations possibles:

abc
acb
bac
bca
cba
cab

Code:

public static void permute(String s) {
    permute(s, 0);
}

private static void permute(String str, int left){
    if(left == str.length()-1) {
        System.out.println(str);
    } else {
        for(int i = left; i < str.length(); i++) {
            String s = swap(str, left, i);
            permute(s, left+1);
        }
    }
}

private static String swap(String s, int left, int right) {
    if (left == right)
        return s;

    String result = s.substring(0, left);
    result += s.substring(right, right+1);
    result += s.substring(left+1, right);
    result += s.substring(left, left+1);
    result += s.substring(right+1);
    return result;
}

la même approche peut être appliquée aux tableaux (au lieu d'une chaîne):

public static void main(String[] args) {
    int[] abc = {1,2,3};
    permute(abc, 0);
}
public static void permute(int[] arr, int index) {
    if (index == arr.length) {
        System.out.println(Arrays.toString(arr));
    } else {
        for (int i = index; i < arr.length; i++) {
            int[] permutation = arr.clone();
            permutation[index] = arr[i];
            permutation[i] = arr[index];
            permute(permutation, index + 1);
        }
    }
}
1
répondu alfasin 2017-08-06 22:43:20

C'est ma solution sur Java:

public class CombinatorialUtils {

    public static void main(String[] args) {
        List<String> alphabet = new ArrayList<>();
        alphabet.add("1");
        alphabet.add("2");
        alphabet.add("3");
        alphabet.add("4");

        for (List<String> strings : permutations(alphabet)) {
            System.out.println(strings);
        }
        System.out.println("-----------");
        for (List<String> strings : combinations(alphabet)) {
            System.out.println(strings);
        }
    }

    public static List<List<String>> combinations(List<String> alphabet) {
        List<List<String>> permutations = permutations(alphabet);
        List<List<String>> combinations = new ArrayList<>(permutations);

        for (int i = alphabet.size(); i > 0; i--) {
            final int n = i;
            combinations.addAll(permutations.stream().map(strings -> strings.subList(0, n)).distinct().collect(Collectors.toList()));
        }
        return combinations;
    }

    public static <T> List<List<T>> permutations(List<T> alphabet) {
        ArrayList<List<T>> permutations = new ArrayList<>();
        if (alphabet.size() == 1) {
            permutations.add(alphabet);
            return permutations;
        } else {
            List<List<T>> subPerm = permutations(alphabet.subList(1, alphabet.size()));
            T addedElem = alphabet.get(0);
            for (int i = 0; i < alphabet.size(); i++) {
                for (List<T> permutation : subPerm) {
                    int index = i;
                    permutations.add(new ArrayList<T>(permutation) {{
                        add(index, addedElem);
                    }});
                }
            }
        }
        return permutations;
    }
}
1
répondu user2153604 2017-08-08 09:59:04

Voici une solution récursive en PHP. Tourbillon de l'après décrit avec précision la logique. Il est intéressant de mentionner que la génération de toutes les permutations s'exécute en temps factoriel, donc il pourrait être une bonne idée d'utiliser une approche itérative à la place.

public function permute($sofar, $input){
  for($i=0; $i < strlen($input); $i++){
    $diff = strDiff($input,$input[$i]);
    $next = $sofar.$input[$i]; //next contains a permutation, save it
    $this->permute($next, $diff);
  }
}

la fonction strDiff prend deux chaînes, s1 et s2 , et renvoie une nouvelle chaîne avec tout dans s1 sans éléments dans s2 (duplicates matière). Donc, strDiff('finish','i') => 'fnish' (le second" i "est et non supprimé).

0
répondu Anthony Naddeo 2013-04-03 01:46:32

voici un algorithme en R, au cas où quelqu'un aurait besoin d'éviter de charger des bibliothèques supplémentaires comme j'ai dû le faire.

permutations <- function(n){
    if(n==1){
        return(matrix(1))
    } else {
        sp <- permutations(n-1)
        p <- nrow(sp)
        A <- matrix(nrow=n*p,ncol=n)
        for(i in 1:n){
            A[(i-1)*p+1:p,] <- cbind(i,sp+(sp>=i))
        }
        return(A)
    }
}

exemple d'usage:

> matrix(letters[permutations(3)],ncol=3)
     [,1] [,2] [,3]
[1,] "a"  "b"  "c" 
[2,] "a"  "c"  "b" 
[3,] "b"  "a"  "c" 
[4,] "b"  "c"  "a" 
[5,] "c"  "a"  "b" 
[6,] "c"  "b"  "a" 
0
répondu Museful 2013-11-25 17:50:59
#!/usr/bin/env python
import time

def permutations(sequence):
  # print sequence
  unit = [1, 2, 1, 2, 1]

  if len(sequence) >= 4:
    for i in range(4, (len(sequence) + 1)):
      unit = ((unit + [i - 1]) * i)[:-1]
      # print unit
    for j in unit:
      temp = sequence[j]
      sequence[j] = sequence[0]
      sequence[0] = temp
      yield sequence
  else:
    print 'You can use PEN and PAPER'


# s = [1,2,3,4,5,6,7,8,9,10]
s = [x for x in 'PYTHON']

print s

z = permutations(s)
try:
  while True:
    # time.sleep(0.0001)
    print next(z)
except StopIteration:
    print 'Done'

['P', 'Y', 'T', 'H', 'O', 'N']
['Y', 'P', 'T', 'H', 'O', 'N']
['T', 'P', 'Y', 'H', 'O', 'N']
['P', 'T', 'Y', 'H', 'O', 'N']
['Y', 'T', 'P', 'H', 'O', 'N']
['T', 'Y', 'P', 'H', 'O', 'N']
['H', 'Y', 'P', 'T', 'O', 'N']
['Y', 'H', 'P', 'T', 'O', 'N']
['P', 'H', 'Y', 'T', 'O', 'N']
['H', 'P', 'Y', 'T', 'O', 'N']
['Y', 'P', 'H', 'T', 'O', 'N']
['P', 'Y', 'H', 'T', 'O', 'N']
['T', 'Y', 'H', 'P', 'O', 'N']
['Y', 'T', 'H', 'P', 'O', 'N']
['H', 'T', 'Y', 'P', 'O', 'N']
['T', 'H', 'Y', 'P', 'O', 'N']
['Y', 'H', 'T', 'P', 'O', 'N']
['H', 'Y', 'T', 'P', 'O', 'N']
['P', 'Y', 'T', 'H', 'O', 'N']
.
.
.
['Y', 'T', 'N', 'H', 'O', 'P']
['N', 'T', 'Y', 'H', 'O', 'P']
['T', 'N', 'Y', 'H', 'O', 'P']
['Y', 'N', 'T', 'H', 'O', 'P']
['N', 'Y', 'T', 'H', 'O', 'P']
0
répondu mahmoh 2014-10-28 05:22:31

Bourne shell solution - dans un total de quatre lignes (sans essai pour aucun cas de param):

test $# -eq 1 && echo "" && exit
for i in $*; do
  "151900920" `echo "$*" | sed -e "s/$i//"` | sed -e "s/^/$i /"
done
0
répondu Peter 2015-02-13 03:28:58

c'est un code récursif pour java, l'idée est d'avoir un préfixe qui ajoute le reste des caractères:

public static void permutation(String str) { 
    permutation("", str); 
}

private static void permutation(String prefix, String str) {
    int n = str.length();
    if (n == 0) System.out.println(prefix);
    else {
        for (int i = 0; i < n; i++)
            permutation(prefix + str.charAt(i), str);
    }
}

exemple:

Input = " ABC"; Sortie:

ABC PBR BAC BCA CAB CBA

0
répondu Rafael Amsili 2016-05-14 21:45:13

juste pour être complet, C++

#include <iostream>
#include <algorithm>
#include <string>

std::string theSeq = "abc";
do
{
  std::cout << theSeq << endl;
} 
while (std::next_permutation(theSeq.begin(), theSeq.end()));

...

abc
acb
bac
bca
cab
cba
0
répondu Anders 2017-04-28 08:15:59

vous ne pouvez pas vraiment parler de résoudre un problème de permutation en récursion sans afficher une implémentation dans un langage (dialectique de) que a été le pionnier de l'idée . Donc, pour être complet, voici une des façons qui peut être fait dans le schéma.

(define (permof wd)
  (cond ((null? wd) '())
        ((null? (cdr wd)) (list wd))
        (else
         (let splice ([l '()] [m (car wd)] [r (cdr wd)])
           (append
            (map (lambda (x) (cons m x)) (permof (append l r)))
            (if (null? r)
                '()
                (splice (cons m l) (car r) (cdr r))))))))

appel (permof (list "foo" "bar" "baz")) nous aurons:

'(("foo" "bar" "baz")
  ("foo" "baz" "bar")
  ("bar" "foo" "baz")
  ("bar" "baz" "foo")
  ("baz" "bar" "foo")
  ("baz" "foo" "bar"))

Je ne vais pas entrer dans les détails de l'algorithme parce qu'il a été suffisamment expliqué dans d'autres messages. Idée est le même.

cependant, les problèmes récursifs ont tendance à être beaucoup plus difficiles à modéliser et à envisager dans un milieu destructeur comme Python, C, et Java, alors que dans Lisp ou ML il peut être exprimé de façon concise.

0
répondu Pie 'Oh' Pah 2017-11-02 21:44:36