Comment générer toutes les permutations d'une liste en Python, indépendamment du type d'éléments dans cette liste?
Par exemple:
permutations([])
[]
permutations([1])
[1]
permutations([1, 2])
[1, 2]
[2, 1]
permutations([1, 2, 3])
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
python
algorithm
permutation
combinatorics
python-2.5
Ricardo Reyes
la source
la source
Réponses:
A partir de Python 2.6 (et si vous êtes sur Python 3) vous disposez d' un standard bibliothèque outil pour cela:
itertools.permutations
.Si vous utilisez un ancien Python (<2.6) pour une raison quelconque ou si vous êtes simplement curieux de savoir comment cela fonctionne, voici une belle approche, tirée de http://code.activestate.com/recipes/252178/ :
Quelques approches alternatives sont répertoriées dans la documentation de
itertools.permutations
. En voici un:Et un autre, basé sur
itertools.product
:la source
for i in range(len(elements))
au lieu defor i in range(len(elements)+1)
. En fait, l'élément isoléelements[0:1]
peut être danslen(elements)
différentes positions, dans le résultat, nonlen(elements)+1
.Et dans Python 2.6 et suivants:
(renvoyé en tant que générateur. Utilisez
list(permutations(l))
pour retourner en tant que liste.)la source
r
paramètre, par exempleitertools.permutations([1,2,3], r=2)
, qui générera toutes les permutations possibles en sélectionnant 2 éléments:[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
Le code suivant avec Python 2.6 et supérieur UNIQUEMENT
Tout d'abord, importez
itertools
:Permutation (l'ordre compte):
Combinaison (l'ordre n'a pas d'importance):
Produit cartésien (avec plusieurs itérables):
Produit cartésien (avec un itérable et lui-même):
la source
appelé comme:
la source
Production:
Comme j'échange le contenu de la liste, un type de séquence modifiable est requis en entrée. Par exemple,
perm(list("ball"))
cela fonctionnera etperm("ball")
ne fonctionnera pas parce que vous ne pouvez pas changer une chaîne.Cette implémentation Python est inspirée de l'algorithme présenté dans le livre Computer Algorithms de Horowitz, Sahni et Rajasekeran .
la source
Cette solution implémente un générateur, pour éviter de conserver toutes les permutations en mémoire:
la source
Dans un style fonctionnel
Le résultat:
la source
Le code suivant est une permutation sur place d'une liste donnée, implémentée en tant que générateur. Comme il ne renvoie que des références à la liste, la liste ne doit pas être modifiée en dehors du générateur. La solution est non récursive, utilise donc une mémoire faible. Fonctionne bien également avec plusieurs copies d'éléments dans la liste d'entrée.
la source
Un moyen assez évident à mon avis pourrait également être:
la source
Production:
la source
J'ai utilisé un algorithme basé sur le système de nombres factoriels - Pour une liste de longueur n, vous pouvez assembler chaque élément de permutation article par article, en sélectionnant parmi les articles laissés à chaque étape. Vous avez n choix pour le premier élément, n-1 pour le second et un seul pour le dernier, vous pouvez donc utiliser les chiffres d'un nombre dans le système de nombres factoriels comme indices. De cette façon, les nombres 0 à n! -1 correspondent à toutes les permutations possibles dans l'ordre lexicographique.
production:
Cette méthode est non récursive, mais elle est légèrement plus lente sur mon ordinateur et xrange déclenche une erreur lorsque n! est trop grand pour être converti en un entier long C (n = 13 pour moi). C'était suffisant quand j'en avais besoin, mais ce n'est pas une itertools.permutations par un long shot.
la source
Notez que cet algorithme a une
n factorial
complexité temporelle, oùn
est la longueur de la liste d'entréeImprimez les résultats sur la course:
Exemple:
Production:
la source
On peut en effet parcourir le premier élément de chaque permutation, comme dans la réponse de tzwenn. Il est cependant plus efficace d'écrire cette solution de cette façon:
Cette solution est environ 30% plus rapide, apparemment grâce à la récursivité se terminant à la
len(elements) <= 1
place de0
. Il est également beaucoup plus efficace en mémoire, car il utilise une fonction de générateur (à traversyield
), comme dans la solution de Riccardo Reyes.la source
Ceci est inspiré par l'implémentation Haskell utilisant la compréhension de liste:
la source
Implémentation régulière (pas de rendement - fera tout en mémoire):
Mise en œuvre du rendement:
L'idée de base est de parcourir tous les éléments du tableau pour la 1ère position, puis en 2e position de parcourir tous les autres éléments sans l'élément choisi pour le 1er, etc. Vous pouvez le faire avec la récursivité , où le le critère d'arrêt est d'arriver à un tableau de 1 élément - auquel cas vous retournez ce tableau.
la source
perms = getPermutations(array[:i] + array[i+1:])
numpy
tableau _>getPermutations(np.array([1, 2, 3]))
, je vois que cela fonctionne pour une liste, je suis juste confus car l'argument func estarray
:)numba
et je suis devenu gourmand avec la vitesse alors j'ai essayé de l'utiliser exclusivement avec desnumpy
tableauxPour les performances, une solution numpy inspirée de Knuth , (p22):
La copie de grands blocs de mémoire permet de gagner du temps - c'est 20 fois plus rapide que
list(itertools.permutations(range(n))
:la source
la source
Voici un algorithme qui fonctionne sur une liste sans créer de nouvelles listes intermédiaires similaires à la solution de Ber sur https://stackoverflow.com/a/108651/184528 .
Vous pouvez essayer le code par vous-même ici: http://repl.it/J9v
la source
La beauté de la récursivité:
la source
Cet algorithme est le plus efficace, il évite le passage de tableaux et la manipulation lors d'appels récursifs, fonctionne en Python 2, 3:
Usage:
la source
la source
UNE AUTRE APPROCHE (sans libs)
L'entrée peut être une chaîne ou une liste
la source
[1, 2, 3]
retours[6, 6, 6, 6, 6, 6]
print(permutation(['1','2','3']))
Avertissement: fiche informée par l'auteur du package. :)
Le package trotter est différent de la plupart des implémentations en ce qu'il génère des pseudo-listes qui ne contiennent pas réellement de permutations mais décrivent plutôt des mappages entre permutations et positions respectives dans un ordre, ce qui permet de travailler avec de très grandes «listes» de permutations, comme indiqué dans cette démo qui effectue des opérations et des recherches assez instantanées dans une pseudo-liste "contenant" toutes les permutations des lettres de l'alphabet, sans utiliser plus de mémoire ou de traitement qu'une page Web typique.
Dans tous les cas, pour générer une liste de permutations, nous pouvons procéder comme suit.
Production:
la source
Générer toutes les permutations possibles
J'utilise python3.4:
Cas de test:
la source
Pour vous faire gagner des heures de recherche et d'expérimentation, voici la solution de permutations non récursives en Python qui fonctionne également avec Numba (à partir de la version 0.41):
Pour donner une impression de performance:
N'utilisez donc cette version que si vous devez l'appeler à partir de la fonction njitted, sinon préférez l'implémentation itertools.
la source
Je vois beaucoup d'itérations en cours à l'intérieur de ces fonctions récursives, pas exactement une récursivité pure ...
donc pour ceux d'entre vous qui ne peuvent pas respecter une seule boucle, voici une solution récursive grossière, totalement inutile
la source
Une autre solution:
la source
Ma solution Python:
la source
Sortie: ['abc', 'acb', 'bac', 'bca', 'cab', 'cba']
la source
En utilisant
Counter
la source