Python'da belirli bir dizenin tüm olası permütasyonlarını bulma


93

Bir ipim var. Bu dizeden tüm permütasyonları, içindeki karakterlerin sırasını değiştirerek oluşturmak istiyorum. Örneğin, şunu söyleyin:

x='stack'

istediğim bunun gibi bir liste

l=['stack','satck','sackt'.......]

Şu anda dizginin liste dökümünü yineliyorum, rastgele 2 harf seçiyorum ve yeni bir dizge oluşturmak için onları transpoze ediyorum ve bunu l'nin set cast'ına ekliyorum. Dizinin uzunluğuna bağlı olarak, olası permütasyon sayısını hesaplıyorum ve set boyutu limite ulaşıncaya kadar yinelemelere devam ediyorum. Bunu yapmanın daha iyi bir yolu olmalı.

Yanıtlar:


148

İtertools modülünün permutations () adında kullanışlı bir yöntemi vardır. Belgeler şunu söylüyor:

itertools.permutations (yinelenebilir [, r])

Yinelemeli öğelerin ardışık r uzunluğu permütasyonlarını döndürür.

R belirtilmezse veya Hiçbiri ise, o zaman varsayılan r yinelenebilir uzunluğa ayarlanır ve tüm olası tam uzunluklu permütasyonlar oluşturulur.

Permütasyonlar sözlükbilimsel sıralama düzeninde yayınlanır. Dolayısıyla, yinelenebilir girdi sıralanırsa, permütasyon dizileri sıralı düzende üretilecektir.

Yine de, izin verilen harflerinizi dizeler olarak birleştirmeniz gerekecek.

>>> from itertools import permutations
>>> perms = [''.join(p) for p in permutations('stack')]
>>> perms

["yığın", "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 ' , 'actks', 'actks', 'ackst', 'ackts', 'akstc', 'aksct', 'aktsc', 'aktcs', 'akcst', 'akcts', 'cstak', 'cstka', ' csatk ',' csakt ',' cskta ',' cskat ',' ctsak ',' ctska ',' ctask ',' ctaks ',' ctksa ',' ctkas ',' castk ',' caskt ',' catsk ' , "kedicikler", "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 ']

Yinelemelerden rahatsızsanız, verilerinizi aşağıdakiler gibi yinelemeleri olmayan bir yapıya sığdırmayı deneyin set:

>>> perms = [''.join(p) for p in permutations('stacks')]
>>> len(perms)
720
>>> len(set(perms))
360

@Pst'e, bunun geleneksel olarak bir tür oyuncu kadrosu olarak düşündüğümüz şey olmadığını, daha çok kurucuya bir çağrı olduğunu belirttiği için teşekkürler set().


3
Nit: set(...)"yayınlamaz". Daha ziyade, girdi koleksiyonunu temsil eden kümeyi üretir (ve verir): bir kez oluşturulduktan sonra, girdi koleksiyonuyla hiçbir ilişkisi yoktur (ve yalnızca farklı bir görünüm değil, farklı bir nesnedir).

@pst: Hmm katılmıyorum. Ada veya Pascal'da, bir dökümün sadece aynı bitler üzerinde yeni bir yazı görünümü olduğunu biliyorum. Bununla birlikte, en azından C açısından bakıldığında, verilerin temel yapısını değiştirseniz de değiştirmeseniz de, çevrim uygun bir terimdir. Basitçe açık tip dönüşümünü ifade eder. Lütfen yapabiliyorsan yanlış anlamamı açıkla.
özlemi yapan makine

1
Tip döküm . Sizin de belirttiğiniz gibi, salt bir görüşten farklı olsa da, karışıklığı önlemek için kavramları ayrı tutmayı ve denemeyi seviyorum. İlk yorumumda "zorlama" dan açıkça bahsetmeliydim, ancak sadece bir işlev ayarlamayı düşünüyordum: list -> set.

1
Bunu görüntülemek bool, bir fonksiyonudur değerlendirir BOOL için (Doğru / Yanlış) olarak girişe bağlı. Burada "cast" kullanımının sahte ve yanıltıcı olduğunu düşünüyorum ...

1
İlginç bir güncelleme olarak, dokümantasyon o zamandan beri değiştirildi. Yerleşik işlev bool (), herhangi bir değeri bir Boolean'a dönüştürmek, özellikle dönüştürmek yerine dönüştürmek için kullanılabilir . Bu, bu tartışmanın sonraki sürümünde oldu ve bu tartışmanın belgelerde bir değişikliğe yol açtığına inanmamı sağladı!
özlem

47

Tüm N alabilirsin! fazla kod içermeyen permütasyonlar

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)

güzel bir. Mükemmel çalışıyor
kishorer747

1
Biraz değiştirdim, eğer i == step
work_in_progress

4
Çalışma zamanı O (n!) Çünkü n! permütasyonlar.
Aspen

step == len(string)Bunun yerine neden kullanıyorsun step == len(string) - 1?
tulians

Çünkü o zaman son 2 öğe asla takas edilmeyecek. B ve c değişene kadar 'abc'yi deneyin.
Roma Riesen

17

İşte minimum kodla dizgenin permütasyonunu yapmanın başka bir yolu. Temelde bir döngü oluştururuz ve sonra aynı anda iki karakteri değiştirmeye devam ederiz, Döngünün içinde özyinelemeye sahip oluruz. Dikkat edin, yalnızca indeksleyiciler dizgimizin uzunluğuna ulaştığında yazdırırız. Örnek: Başlangıç ​​noktamız için ABC i ve döngümüz için özyineleme param j

İşte soldan sağa yukarıdan aşağıya nasıl çalıştığı görsel bir yardım (permütasyon sırasıdır)

görüntü açıklamasını buraya girin

kod:

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)

5
Bunun bakteri izleme paradigmasının temeli olduğunu belirtmek faydalı olabilir .
AruniRC

Daha fazla bilgi, aynı / benzer kodlar: geeksforgeeks.org/… Örneğinizi grafik örnekle daha çok beğendim;)
CTS_AE

8

Stack Overflow kullanıcıları zaten bazı güçlü çözümler yayınladılar ancak ben başka bir çözüm daha göstermek istedim. Bunu daha sezgisel buluyorum

Buradaki fikir, belirli bir dizge için: algoritmaya göre tekrarlayabiliriz (sözde kod):

permütasyonlar = karakter + permütasyonlar (dize - karakter) dizedeki karakter için

Umarım birine yardımcı olur!

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

4
Bu, tekrar eden karakterlerin (str.replace) olduğu durumlarda çalışmayacaktır. Örn: rqqx
sanjay

Kullanın: [permutation_list.append (char + a) in permütasyonlar için (string.replace (char, "", 1))]
user3761855

7

Benzersiz permütasyonlar döndürmek için basit bir işlev:

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)

6
1. Bir yazım hatası var: revursive_perms-> recursive_perms. 2. recursive_permsReturn deyiminde bir kümeye dönüştürdüğünüz bir liste yerine bir küme olsaydı RAM ve zamandan tasarruf ederdi . 3. .replacearg 'yi özyinelemeli çağrısına yapılandırmak yerine dizge dilimlemeyi kullanmak daha verimli olacaktır permutations. 4. stringDeğişken adı olarak kullanmak iyi bir fikir değildir çünkü bu, standart stringmodülün adını gölgeler .
PM 2Ring

5

İşte @Adriano ve @illerucis'in gönderdiklerinden farklı bir yaklaşım. Bunun daha iyi bir çalışma süresi var, zamanı ölçerek kendiniz kontrol edebilirsiniz:

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

Rasgele bir "dadffddxcf" dizisi için permütasyon kitaplığı için 1.1336 saniye, bu uygulama için 9.125 saniye ve @ Adriano ve @illerucis'in sürümü için 16.357 saniye sürdü. Elbette yine de optimize edebilirsiniz.


4

itertools.permutationsiyidir, ancak yinelenen öğeler içeren dizilerle iyi bir şekilde ilgilenmez. Bunun nedeni, dahili olarak sekans indekslerine izin vermesi ve sekans öğesi değerlerinden habersiz olmasıdır.

Elbette, itertools.permutationskopyaları ortadan kaldırmak için bir setin çıktısını filtrelemek mümkündür , ancak yine de bu kopyaları oluşturmak için zaman harcar ve temel dizide birkaç tekrarlanan öğe varsa, çok sayıda kopya olacaktır. Ayrıca, sonuçları tutmak için bir koleksiyon kullanmak RAM'i boşa harcar ve ilk etapta bir yineleyici kullanmanın yararını ortadan kaldırır.

Neyse ki, daha verimli yaklaşımlar var. Aşağıdaki kod, Vikipedi'deki Permütasyon makalesinde bulunabilecek 14. yüzyıl Hintli matematikçi Narayana Pandita'nın algoritmasını kullanıyor . Bu eski algoritma, sırayla permütasyon oluşturmanın bilinen en hızlı yollarından biridir ve yinelenen öğeleri içeren permütasyonları düzgün bir şekilde yönetmesi açısından oldukça sağlamdır.

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)

çıktı

aadt
aatd
adat
adta
atad
atda
daat
data
dtaa
taad
tada
tdaa

Elbette, verilen dizeleri bir liste halinde toplamak istiyorsanız, şunları yapabilirsiniz:

list(lexico_permute_string('data'))

veya son Python sürümlerinde:

[*lexico_permute_string('data')]

Güzelce açıklanmış.
lmao

2

neden basit yapmıyorsun:

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))

gördüğünüz gibi hiçbir kopya alamazsınız:

 ['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]

5
Hayır, iki veya daha fazla aynı harfiniz varsa her zaman kopyalar (veya daha kötü) alırsınız. O kelime kullanıldığı gibi bu, @ machineyearning örneğinde de olduğu yığınları yerine istifi . Bunun anlamı şudur: Çözümünüz yalnızca içinde benzersiz karakterler bulunan sözcükler için işe yarar.
erik

2
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')))

2
Çözümünüzün neden daha önce sağlanandan daha iyi olduğunu açıklayabilir misiniz?
Noel Widmer

Çözümümün diğerlerinden daha iyi olduğunu söylemedim. Ben sadece bunun için çözümümü sağladım.
Srivastava


1

Aşağıda , farklı karakterlere sahip bir dizenin tüm permütasyonlarının bir listesini itertools kullanmadan döndürmek için illerucis kodunun biraz geliştirilmiş bir sürümü bulunmaktadır s(sözlükbilimsel sıralama düzeninde olması gerekmez):

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

1

Yine başka bir girişim ve özyinelemeli çözüm. Buradaki fikir, özet olarak bir harf seçmek ve ardından bir kelime oluşturmaktır.

# 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)

Çıktı:

abc
acb
bac
bca
cab
cba

0

İşte gerçekten basit bir jeneratör versiyonu:

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)

Bence o kadar kötü değil


0
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

lütfen bir açıklama eklemeyi deneyin.
Arun Vinoth

0

İşte basit ve anlaşılır özyinelemeli uygulama;

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

1
Girintiyi düzeltmelisiniz. Yinelemeli aramanın sonuçlarını stringPermutationsbir listeye kaydetmenize gerek yoktur - doğrudan üzerinde yineleme yapabilirsiniz, örn for perm in stringPermutations(s[:pos] + s[pos+1:]):. Ayrıca, kolaylaştırabilirsiniz forkullanarak döngü enumerateyerine rangeve ortadan char = s[pos]atama: for pos, char in enumerate(s):.
PM 2Ring

0
from itertools import permutations
perms = [''.join(p) for p in permutations('ABC')]

perms = [''.join(p) for p in permutations('stack')]

5
lütfen bir açıklama eklemeyi deneyin.
Arun Vinoth

0
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"))

Bu, özyinelemeli permütasyonlar oluşturmanın bir yoludur, girdi olarak 'a', 'ab' ve 'abc' dizelerini alarak kodu kolayca anlayabilirsiniz.

Tüm N'yi aldın! bununla permütasyonlar, kopyalar olmadan.


0

Herkes kendi kodunun kokusunu sever. Sadece en basit bulduğumu paylaşıyorum:

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

0

Bu program kopyaları ortadan kaldırmaz, ancak bence en verimli yaklaşımlardan biri:

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

0
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)

lütfen bir açıklama eklemeyi deneyin.
Arun Vinoth

0

Permütasyon kullanarak daha basit çözüm.

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)

0

Yığınla Tüm Olası Kelime

from itertools import permutations
for i in permutations('stack'):
    print(''.join(i))
permutations(iterable, r=None)

Yinelemeli öğelerin ardışık r uzunluğu permütasyonlarını döndürür.

R belirtilmezse veya Hiçbiri ise, o zaman varsayılan r yinelenebilir uzunluğa ayarlanır ve tüm olası tam uzunluklu permütasyonlar oluşturulur.

Permütasyonlar sözlükbilimsel sıralama düzeninde yayınlanır. Dolayısıyla, yinelenebilir girdi sıralanırsa, permütasyon dizileri sıralı düzende üretilecektir.

Öğeler, değerlerine değil konumlarına göre benzersiz olarak değerlendirilir. Dolayısıyla, giriş öğeleri benzersizse, her permütasyonda tekrar değeri olmayacaktır.


0

Bu, n!dizedeki yinelenen öğeleri kabul eden özyinelemeli bir çözümdür

import 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

Çözümü iki unsuru hesaba katarak doğruladım, kombinasyon sayısıdır n!ve sonuç kopya içeremez. Yani:

inpt = "1234"
results = getFactors("",inpt)

if len(results) == math.factorial(len(inpt)) | len(results) != len(set(results)):
    print("Wrong approach")
else:
    print("Correct Approach")

0

Özyinelemeli yaklaşımla.

def permute(word):
    if len(word) == 1:
        return [word]
    permutations = permute(word[1:])
    character = word[0]
    result = []
    for p in permutations:
        for i in range(len(p)+1):
            result.append(p[:i] + character + p[i:])
    return result




running code.

>>> permute('abc')
['abc', 'bac', 'bca', 'acb', 'cab', 'cba']

-1

Özyineleme ile

# 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)

Yinelemeli yaklaşımla (Stack Kullanma)

# 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)

Sözlüksel olarak sıralanmış

# 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)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.