Vous devrez cependant joindre vos lettres permutées sous forme de chaînes.
['stack', 'stakc', 'stcak', 'stcka', 'stkac', 'stkca', 'satck', 'satkc', 'sactk', 'sackt', 'saktc', 'sakct', ' sctak ',' sctka ',' scatk ',' scakt ',' sckta ',' sckat ',' sktac ',' sktca ',' skatc ',' skact ',' skcta ',' skcat ',' tsack ' , 'tsakc', 'tscak', 'tscka', 'tskac', 'tskca', 'tasck', 'taskc', 'tacsk', 'tacks', 'taksc', 'takcs', 'tcsak', ' tcska ',' tcask ',' tcaks ',' tcksa ',' tckas ',' tksac ',' tksca ',' tkasc ',' tkacs ',' tkcsa ',' tkcas ',' astck ','astkc ',' asctk ',' asckt ',' asktc ',' askct ',' atsck ',' atskc ',' atcsk ',' atcks ',' atksc ',' atkcs ',' acstk ',' acskt ' , 'actesk', 'actks', 'ackst', 'ackts', 'akstc', 'aksct', 'aktsc', 'aktcs', 'akcst', 'akcts', 'cstak', 'cstka', ' csatk ',' csakt ',' cskta ',' cskat ',' ctsak ',' ctska ',' ctask ',' ctaks ',' ctksa ',' ctkas ',' castk ',' caskt ',' catsk ' , 'catks', 'cakst', 'cakts', 'cksta', 'cksat', 'cktsa', 'cktas', 'ckast', 'ckats', 'kstac', 'kstca', 'ksatc','ksact', 'kscta', 'kscat', 'ktsac', 'ktsca', 'ktasc', 'ktacs', 'ktcsa', 'ktcas', 'kastc', 'kasct', 'katsc', 'katcs ',' kacst ',' kacts ',' kcsta ',' kcsat ',' kctsa ',' kctas ',' kcast ',' kcats ']
Si vous vous trouvez troublé par des doublons, essayez d'ajuster vos données dans une structure sans doublons comme set
:
Merci à @pst d'avoir souligné que ce n'est pas ce que nous considérons traditionnellement comme un cast de type, mais plutôt un appel au set()
constructeur.
set(...)
ne «lance» pas. Au contraire, il génère (et produit) l'ensemble représentant la collection d'entrée: une fois généré, il n'a aucune association avec la collection d'entrée (et est un objet différent, pas seulement une vue différente).bool
, est une fonction qui évalue un booléen (Vrai / Faux) en fonction de l'entrée. Je trouve que l'utilisation de "cast" ici est fausse et trompeuse ...Vous pouvez obtenir tous les N! permutations sans trop de code
def permutations(string, step = 0): # if we've gotten to the end, print the permutation if step == len(string): print "".join(string) # everything to the right of step has not been swapped yet for i in range(step, len(string)): # copy the string (store as array) string_copy = [character for character in string] # swap the current index with the step string_copy[step], string_copy[i] = string_copy[i], string_copy[step] # recurse on the portion of the string that has not been swapped yet (now it's index will begin with step + 1) permutations(string_copy, step + 1)
la source
step == len(string)
au lieu destep == len(string) - 1
?Voici une autre façon de faire la permutation de chaîne avec un code minimal. Nous créons essentiellement une boucle, puis nous continuons à échanger deux caractères à la fois, à l'intérieur de la boucle, nous aurons la récursivité. Remarquez, nous n'imprimons que lorsque les indexeurs atteignent la longueur de notre chaîne. Exemple: ABC i pour notre point de départ et notre paramètre de récursivité j pour notre boucle
voici une aide visuelle comment ça marche de gauche à droite de haut en bas (c'est l'ordre de permutation)
le code :
def permute(data, i, length): if i==length: print(''.join(data) ) else: for j in range(i,length): #swap data[i], data[j] = data[j], data[i] permute(data, i+1, length) data[i], data[j] = data[j], data[i] string = "ABC" n = len(string) data = list(string) permute(data, 0, n)
la source
Les utilisateurs de Stack Overflow ont déjà publié des solutions solides, mais je voulais montrer encore une autre solution. Celui-ci je trouve plus intuitif
L'idée est que pour une chaîne donnée: on peut récurer par l'algorithme (pseudo-code):
J'espère que cela aide quelqu'un!
def permutations(string): """ Create all permutations of a string with non-repeating characters """ permutation_list = [] if len(string) == 1: return [string] else: for char in string: [permutation_list.append(char + a) for a in permutations(string.replace(char, "", 1))] return permutation_list
la source
Voici une fonction simple pour renvoyer des permutations uniques:
def permutations(string): if len(string) == 1: return string recursive_perms = [] for c in string: for perm in permutations(string.replace(c,'',1)): revursive_perms.append(c+perm) return set(revursive_perms)
la source
revursive_perms
->recursive_perms
. 2. Cela permettrait d'économiser de la RAM et du temps s'ilrecursive_perms
s'agissait d'un ensemble plutôt qu'une liste que vous convertissez en un ensemble dans l'instruction return. 3. Il serait plus efficace d'utiliser le découpage de chaînes au lieu de.replace
construire l'argument selon l'appel récursif depermutations
. 4. Ce n'est pas une bonne idée de l'utiliserstring
comme nom de variable car cela occulte le nom dustring
module standard .Voici une autre approche différente de ce que @Adriano et @illerucis ont publié. Cela a un meilleur temps d'exécution, vous pouvez le vérifier vous-même en mesurant le temps:
def removeCharFromStr(str, index): endIndex = index if index == len(str) else index + 1 return str[:index] + str[endIndex:] # 'ab' -> a + 'b', b + 'a' # 'abc' -> a + bc, b + ac, c + ab # a + cb, b + ca, c + ba def perm(str): if len(str) <= 1: return {str} permSet = set() for i, c in enumerate(str): newStr = removeCharFromStr(str, i) retSet = perm(newStr) for elem in retSet: permSet.add(c + elem) return permSet
Pour une chaîne arbitraire "dadffddxcf", il a fallu 1,1336 sec pour la bibliothèque de permutation, 9,125 sec pour cette implémentation et 16,357 sec pour la version de @ Adriano et @illerucis. Bien sûr, vous pouvez toujours l'optimiser.
la source
itertools.permutations
c'est bien, mais cela ne gère pas bien les séquences qui contiennent des éléments répétés. En effet, en interne, il permute les indices de séquence et ignore les valeurs des éléments de séquence.Bien sûr, il est possible de filtrer la sortie de
itertools.permutations
via un ensemble pour éliminer les doublons, mais cela perd encore du temps à générer ces doublons, et s'il y a plusieurs éléments répétés dans la séquence de base, il y en aura beaucoup de doublons. En outre, l'utilisation d'une collection pour contenir les résultats gaspille de la RAM, annulant l'avantage d'utiliser un itérateur en premier lieu.Heureusement, il existe des approches plus efficaces. Le code ci-dessous utilise l'algorithme du mathématicien indien du 14ème siècle Narayana Pandita, que l'on peut trouver dans l'article de Wikipédia sur la permutation . Cet algorithme ancien est toujours l'un des moyens connus les plus rapides pour générer des permutations dans l'ordre, et il est assez robuste, en ce sens qu'il gère correctement les permutations qui contiennent des éléments répétés.
def lexico_permute_string(s): ''' Generate all permutations in lexicographic order of string `s` This algorithm, due to Narayana Pandita, is from https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order To produce the next permutation in lexicographic order of sequence `a` 1. Find the largest index j such that a[j] < a[j + 1]. If no such index exists, the permutation is the last permutation. 2. Find the largest index k greater than j such that a[j] < a[k]. 3. Swap the value of a[j] with that of a[k]. 4. Reverse the sequence from a[j + 1] up to and including the final element a[n]. ''' a = sorted(s) n = len(a) - 1 while True: yield ''.join(a) #1. Find the largest index j such that a[j] < a[j + 1] for j in range(n-1, -1, -1): if a[j] < a[j + 1]: break else: return #2. Find the largest index k greater than j such that a[j] < a[k] v = a[j] for k in range(n, j, -1): if v < a[k]: break #3. Swap the value of a[j] with that of a[k]. a[j], a[k] = a[k], a[j] #4. Reverse the tail of the sequence a[j+1:] = a[j+1:][::-1] for s in lexico_permute_string('data'): print(s)
production
Bien sûr, si vous souhaitez rassembler les chaînes générées dans une liste, vous pouvez faire
list(lexico_permute_string('data'))
ou dans les versions récentes de Python:
[*lexico_permute_string('data')]
la source
pourquoi ne faites-vous pas simplement:
from itertools import permutations perms = [''.join(p) for p in permutations(['s','t','a','c','k'])] print perms print len(perms) print len(set(perms))
vous n'obtenez aucun duplicata comme vous pouvez le voir:
['stack', 'stakc', 'stcak', 'stcka', 'stkac', 'stkca', 'satck', 'satkc', 'sactk', 'sackt', 'saktc', 'sakct', 'sctak', 'sctka', 'scatk', 'scakt', 'sckta', 'sckat', 'sktac', 'sktca', 'skatc', 'skact', 'skcta', 'skcat', 'tsack', 'tsakc', 'tscak', 'tscka', 'tskac', 'tskca', 'tasck', 'taskc', 'tacsk', 'tacks', 'taksc', 'takcs', 'tcsak', 'tcska', 'tcask', 'tcaks', 'tcksa', 'tckas', 'tksac', 'tksca', 'tkasc', 'tkacs', 'tkcsa', 'tkcas', 'astck', 'astkc', 'asctk', 'asckt', 'asktc', 'askct', 'atsck', 'atskc', 'atcsk', 'atcks', 'atksc', 'atkcs', 'acstk', 'acskt', 'actsk', 'actks', 'ackst', 'ackts', 'akstc', 'aksct', 'aktsc', 'aktcs', 'akcst', 'akcts', 'cstak', 'cstka', 'csatk', 'csakt', 'cskta', 'cskat', 'ctsak', 'ctska', 'ctask', 'ctaks', 'ctksa', 'ctkas', 'castk', 'caskt', 'catsk', 'catks', 'cakst', 'cakts', 'cksta', 'cksat', 'cktsa', 'cktas', 'ckast', 'ckats', 'kstac', 'kstca', 'ksatc', 'ksact', 'kscta', 'kscat', 'ktsac', 'ktsca', 'ktasc', 'ktacs', 'ktcsa', 'ktcas', 'kastc', 'kasct', 'katsc', 'katcs', 'kacst', 'kacts', 'kcsta', 'kcsat', 'kctsa', 'kctas', 'kcast', 'kcats'] 120 120 [Finished in 0.3s]
la source
def permute(seq): if not seq: yield seq else: for i in range(len(seq)): rest = seq[:i]+seq[i+1:] for x in permute(rest): yield seq[i:i+1]+x print(list(permute('stack')))
la source
Voir
itertools.combinations
ouitertools.permutations
.la source
Voici une version légèrement améliorée du code d' illerucis pour renvoyer une liste de toutes les permutations d'une chaîne
s
avec des caractères distincts (pas nécessairement dans l'ordre de tri lexicographique), sans utiliser itertools:def get_perms(s, i=0): """ Returns a list of all (len(s) - i)! permutations t of s where t[:i] = s[:i]. """ # To avoid memory allocations for intermediate strings, use a list of chars. if isinstance(s, str): s = list(s) # Base Case: 0! = 1! = 1. # Store the only permutation as an immutable string, not a mutable list. if i >= len(s) - 1: return ["".join(s)] # Inductive Step: (len(s) - i)! = (len(s) - i) * (len(s) - i - 1)! # Swap in each suffix character to be at the beginning of the suffix. perms = get_perms(s, i + 1) for j in range(i + 1, len(s)): s[i], s[j] = s[j], s[i] perms.extend(get_perms(s, i + 1)) s[i], s[j] = s[j], s[i] return perms
la source
Encore une initiative et une solution récursive. L'idée est de sélectionner une lettre comme pivot puis de créer un mot.
# for a string with length n, there is a factorial n! permutations alphabet = 'abc' starting_perm = '' # with recursion def premuate(perm, alphabet): if not alphabet: # we created one word by using all letters in the alphabet print(perm + alphabet) else: for i in range(len(alphabet)): # iterate over all letters in the alphabet premuate(perm + alphabet[i], alphabet[0:i] + alphabet[i+1:]) # chose one letter from the alphabet # call it premuate(starting_perm, alphabet)
Production:
la source
Voici une version de générateur vraiment simple:
def find_all_permutations(s, curr=[]): if len(s) == 0: yield curr else: for i, c in enumerate(s): for combo in find_all_permutations(s[:i]+s[i+1:], curr + [c]): yield "".join(combo)
Je pense que ce n'est pas si mal!
la source
def f(s): if len(s) == 2: X = [s, (s[1] + s[0])] return X else: list1 = [] for i in range(0, len(s)): Y = f(s[0:i] + s[i+1: len(s)]) for j in Y: list1.append(s[i] + j) return list1 s = raw_input() z = f(s) print z
la source
from itertools import permutations perms = [''.join(p) for p in permutations('ABC')] perms = [''.join(p) for p in permutations('stack')]
la source
def perm(string): res=[] for j in range(0,len(string)): if(len(string)>1): for i in perm(string[1:]): res.append(string[0]+i) else: return [string]; string=string[1:]+string[0]; return res; l=set(perm("abcde"))
C'est une façon de générer des permutations avec récursivité, vous pouvez facilement comprendre le code en prenant les chaînes 'a', 'ab' et 'abc' comme entrée.
Vous obtenez tous les N! permutations avec cela, sans doublons.
la source
Tout le monde aime l'odeur de son propre code. Je partage simplement celui que je trouve le plus simple:
def get_permutations(word): if len(word) == 1: yield word for i, letter in enumerate(word): for perm in get_permutations(word[:i] + word[i+1:]): yield letter + perm
la source
Ce programme n'élimine pas les doublons, mais je pense que c'est l'une des approches les plus efficaces:
s=raw_input("Enter a string: ") print "Permutations :\n",s size=len(s) lis=list(range(0,size)) while(True): k=-1 while(k>-size and lis[k-1]>lis[k]): k-=1 if k>-size: p=sorted(lis[k-1:]) e=p[p.index(lis[k-1])+1] lis.insert(k-1,'A') lis.remove(e) lis[lis.index('A')]=e lis[k:]=sorted(lis[k:]) list2=[] for k in lis: list2.append(s[k]) print "".join(list2) else: break
la source
def permute_all_chars(list, begin, end): if (begin == end): print(list) return for current_position in range(begin, end + 1): list[begin], list[current_position] = list[current_position], list[begin] permute_all_chars(list, begin + 1, end) list[begin], list[current_position] = list[current_position], list[begin] given_str = 'ABC' list = [] for char in given_str: list.append(char) permute_all_chars(list, 0, len(list) -1)
la source
Solution plus simple utilisant des permutations.
from itertools import permutations def stringPermutate(s1): length=len(s1) if length < 2: return s1 perm = [''.join(p) for p in permutations(s1)] return set(perm)
la source
Tous les mots possibles avec pile
from itertools import permutations for i in permutations('stack'): print(''.join(i))
permutations(iterable, r=None)
Renvoie des permutations successives de longueur r des éléments de l'itérable.
Si r n'est pas spécifié ou est None, alors r prend par défaut la longueur de l'itérable et toutes les permutations de pleine longueur possibles sont générées.
Les permutations sont émises dans l'ordre de tri lexicographique. Ainsi, si l'itérable d'entrée est trié, les tuples de permutation seront produits dans l'ordre trié.
Les éléments sont traités comme uniques en fonction de leur position et non de leur valeur. Donc, si les éléments d'entrée sont uniques, il n'y aura pas de valeurs de répétition dans chaque permutation.
la source
Il s'agit d'une solution récursive avec
n!
laquelle accepte les éléments en double dans la chaîneimport math def getFactors(root,num): sol = [] # return condition if len(num) == 1: return [root+num] # looping in next iteration for i in range(len(num)): # Creating a substring with all remaining char but the taken in this iteration if i > 0: rem = num[:i]+num[i+1:] else: rem = num[i+1:] # Concatenating existing solutions with the solution of this iteration sol = sol + getFactors(root + num[i], rem) return sol
J'ai validé la solution en tenant compte de deux éléments, le nombre de combinaisons est
n!
et le résultat ne peut pas contenir de doublons. Donc:inpt = "1234" results = getFactors("",inpt) if len(results) == math.factorial(len(inpt)) | len(results) != len(set(results)): print("Wrong approach") else: print("Correct Approach")
la source
Voici une implémentation récursive simple et directe;
def stringPermutations(s): if len(s) < 2: yield s return for pos in range(0, len(s)): char = s[pos] permForRemaining = list(stringPermutations(s[0:pos] + s[pos+1:])) for perm in permForRemaining: yield char + perm
la source
stringPermutations
dans une liste - vous pouvez effectuer une itération directement dessus, par exemplefor perm in stringPermutations(s[:pos] + s[pos+1:]):
. En outre, vous pouvez simplifier lafor
boucle en utilisant auenumerate
lieu derange
et éliminer lachar = s[pos]
cession:for pos, char in enumerate(s):
.# swap ith and jth character of string def swap(s, i, j): q = list(s) q[i], q[j] = q[j], q[i] return ''.join(q) # recursive function def _permute(p, s, permutes): if p >= len(s) - 1: permutes.append(s) return for i in range(p, len(s)): _permute(p + 1, swap(s, p, i), permutes) # helper function def permute(s): permutes = [] _permute(0, s, permutes) return permutes # TEST IT s = "1234" all_permute = permute(s) print(all_permute)
# swap ith and jth character of string def swap(s, i, j): q = list(s) q[i], q[j] = q[j], q[i] return ''.join(q) # iterative function def permute_using_stack(s): stk = [(0, s)] permutes = [] while len(stk) > 0: p, s = stk.pop(0) if p >= len(s) - 1: permutes.append(s) continue for i in range(p, len(s)): stk.append((p + 1, swap(s, p, i))) return permutes # TEST IT s = "1234" all_permute = permute_using_stack(s) print(all_permute)
# swap ith and jth character of string def swap(s, i, j): q = list(s) q[i], q[j] = q[j], q[i] return ''.join(q) # finds next lexicographic string if exist otherwise returns -1 def next_lexicographical(s): for i in range(len(s) - 2, -1, -1): if s[i] < s[i + 1]: m = s[i + 1] swap_pos = i + 1 for j in range(i + 1, len(s)): if m > s[j] > s[i]: m = s[j] swap_pos = j if swap_pos != -1: s = swap(s, i, swap_pos) s = s[:i + 1] + ''.join(sorted(s[i + 1:])) return s return -1 # helper function def permute_lexicographically(s): s = ''.join(sorted(s)) permutes = [] while True: permutes.append(s) s = next_lexicographical(s) if s == -1: break return permutes # TEST IT s = "1234" all_permute = permute_lexicographically(s) print(all_permute)
la source