Menemukan semua kemungkinan permutasi dari string tertentu dengan python

93

Saya memiliki tali. Saya ingin menghasilkan semua permutasi dari string itu, dengan mengubah urutan karakter di dalamnya. Misalnya, katakan:

x='stack'

yang saya inginkan adalah daftar seperti ini,

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

Saat ini saya melakukan iterasi pada daftar cast string, mengambil 2 huruf secara acak dan mengubahnya menjadi string baru, dan menambahkannya ke set cast l. Berdasarkan panjang string, saya menghitung jumlah permutasi yang mungkin dan melanjutkan iterasi hingga ukuran yang ditetapkan mencapai batas. Pasti ada cara yang lebih baik untuk melakukan ini.

Nihar Sarangi
sumber

Jawaban:

148

Modul itertools memiliki metode berguna yang disebut permutasi (). Dokumentasinya mengatakan:

itertools.permutations (iterable [, r])

Kembalikan permutasi panjang r elemen yang berurutan dalam iterable.

Jika r tidak ditentukan atau Tidak ada, maka r default ke panjang iterable dan semua kemungkinan permutasi panjang penuh dihasilkan.

Permutasi dipancarkan dalam urutan leksikografik. Jadi, jika input iterable diurutkan, permutasi tupel akan diproduksi dalam urutan yang diurutkan.

Anda harus menggabungkan huruf yang diubah sebagai string.

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

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

Jika Anda bermasalah dengan duplikat, coba paskan data Anda ke dalam struktur tanpa duplikat seperti set:

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

Terima kasih kepada @pst karena telah menunjukkan bahwa ini bukanlah apa yang secara tradisional kami anggap sebagai pemeran tipe, tetapi lebih merupakan panggilan ke set()konstruktor.

kerinduan mesin
sumber
3
Nit: set(...)tidak "dilemparkan". Sebaliknya, ia menghasilkan (dan menghasilkan) set yang mewakili koleksi masukan: setelah dibuat ia tidak memiliki kaitan dengan koleksi masukan (dan merupakan objek yang berbeda, bukan hanya tampilan yang berbeda).
@pst: Hmm saya cenderung tidak setuju. Saya tahu di Ada atau Pascal bahwa pemeran hanyalah tampilan tipe baru pada bit yang sama. Namun setidaknya dari perspektif C, casting adalah istilah yang tepat baik Anda mengubah struktur yang mendasari data atau tidak. Ini hanya mengacu pada jenis konversi eksplisit. Tolong jelaskan kesalahpahaman saya jika Anda bisa.
mesin merindukan
1
Typecasting . Sementara, seperti yang Anda tunjukkan, ini mungkin berbeda dari sekadar pandangan, saya suka mencoba dan memisahkan konsep untuk menghindari kebingungan. Saya seharusnya menyebutkan "paksaan" secara eksplisit dalam komentar pertama saya, meskipun saya hanya akan mempertimbangkan set a function: list -> set.
1
Saya melihatnya bool,, adalah fungsi yang mengevaluasi ke bool (True / False) tergantung pada input. Saya menemukan penggunaan "cast" di sini palsu dan menyesatkan ...
1
Sebagai pembaruan yang menarik, dokumentasinya telah diubah menjadi The built-in function bool () dapat digunakan untuk mengonversi nilai apa pun menjadi Boolean , secara khusus mengonversi daripada mentransmisikan. Ini terjadi pada rilis berikutnya untuk diskusi ini, membuat saya percaya bahwa diskusi ini mengarah pada perubahan dalam dokumen!
mesin merindukan
46

Anda bisa mendapatkan semua N! permutasi tanpa banyak kode

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)
illerucis
sumber
bagus. Bekerja dengan sempurna
kishorer747
1
Saya hanya sedikit memodifikasinya, kita tidak perlu menukar variabel jika i == step
work_in_progress
4
Runtime adalah O (n!) Karena ada n! permutasi.
Aspen
Mengapa Anda menggunakan, step == len(string)bukan step == len(string) - 1?
tulian
Karena dengan demikian 2 item terakhir tidak akan pernah bisa ditukar. Coba 'abc' sampai b dan c ditukar.
Roman Riesen
16

Berikut adalah cara lain untuk melakukan permutasi string dengan kode minimal. Kami pada dasarnya membuat loop dan kemudian kami terus menukar dua karakter sekaligus, Di dalam loop kami akan melakukan rekursi. Perhatikan, kami hanya mencetak ketika pengindeks mencapai panjang string kami. Contoh: ABC i untuk titik awal kita dan parameter rekursi kita j untuk loop kita

berikut adalah bantuan visual cara kerjanya dari kiri ke kanan atas ke bawah (adalah urutan permutasi)

masukkan deskripsi gambar di sini

Kode :

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)
grepit
sumber
5
Mungkin bermanfaat untuk menyebutkan bahwa ini adalah dasar dari paradigma bactracking .
AruniRC
Info lebih lanjut, kode yang sama / serupa: geeksforgeeks.org/… Saya lebih suka contoh Anda meskipun dengan contoh grafik;)
CTS_AE
8

Pengguna Stack Overflow telah memposting beberapa solusi kuat tetapi saya ingin menunjukkan solusi lain. Yang ini menurut saya lebih intuitif

Idenya adalah untuk string yang diberikan: kita dapat menggunakan algoritma (pseudo-code):

permutasi = char + permutasi (string - char) untuk char dalam string

Saya harap ini membantu seseorang!

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
BushMinusZero
sumber
4
Ini tidak akan berfungsi untuk kasus di mana ada karakter berulang (str.replace). Misalnya: rqqx
sanjay
Gunakan: [permutation_list.append (char + a) untuk di permutasi (string.replace (char, "", 1))]
user3761855
7

Berikut fungsi sederhana untuk mengembalikan permutasi unik:

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)
ArashkG
sumber
6
1. Anda salah ketik: revursive_perms-> recursive_perms. 2. Ini akan menghemat RAM dan waktu jika recursive_permsadalah satu set daripada daftar yang Anda ubah ke satu set dalam pernyataan return. 3. Akan lebih efisien untuk menggunakan pemotongan string daripada .replacemembangun arg ke panggilan rekursif permutations. 4. Ini bukan ide yang baik untuk digunakan stringsebagai nama variabel karena bayangan nama stringmodul standar .
PM 2Ring
5

Berikut pendekatan lain yang berbeda dari apa yang diposting @Adriano dan @illerucis. Ini memiliki runtime yang lebih baik, Anda dapat memeriksanya sendiri dengan mengukur waktu:

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

Untuk sembarang string "dadffddxcf" butuh 1,1336 detik untuk perpustakaan permutasi, 9,125 detik untuk implementasi ini dan 16,357 detik untuk versi @ Adriano dan @illerucis. Tentu Anda tetap bisa mengoptimalkannya.

Rooky
sumber
4

itertools.permutationsbagus, tetapi tidak cocok dengan urutan yang mengandung elemen berulang. Itu karena secara internal itu mengizinkan indeks urutan dan tidak menyadari nilai item urutan.

Tentu, itu mungkin untuk memfilter keluaran itertools.permutationsmelalui satu set untuk menghilangkan duplikat, tetapi masih membuang waktu menghasilkan duplikat tersebut, dan jika ada beberapa elemen berulang dalam urutan dasar akan ada banyak duplikat. Selain itu, menggunakan collection untuk menahan hasil akan membuang-buang RAM, meniadakan manfaat penggunaan iterator di tempat pertama.

Untungnya, ada pendekatan yang lebih efisien. Kode di bawah ini menggunakan algoritme ahli matematika India abad ke-14, Narayana Pandita, yang dapat ditemukan di artikel Wikipedia tentang Permutasi . Algoritme kuno ini masih merupakan salah satu cara tercepat yang diketahui untuk menghasilkan permutasi secara berurutan, dan ini cukup kuat, karena menangani permutasi yang mengandung elemen berulang dengan benar.

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)

keluaran

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

Tentu saja, jika Anda ingin mengumpulkan string yang dihasilkan ke dalam daftar yang dapat Anda lakukan

list(lexico_permute_string('data'))

atau dalam versi Python terbaru:

[*lexico_permute_string('data')]
PM 2Ring
sumber
Dijelaskan dengan indah.
lmao
2

kenapa kamu tidak sederhana melakukan:

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

Anda tidak mendapatkan duplikat seperti yang Anda lihat:

 ['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]
Vincenzo
sumber
5
Tidak, Anda selalu mendapatkan duplikat (atau lebih buruk) jika Anda memiliki dua atau lebih huruf yang sama. Itu adalah kasus dalam contoh @ machineyearning, saat dia menggunakan kata stack, bukan stack . Artinya: Solusi Anda hanya berfungsi untuk kata-kata dengan karakter unik di dalamnya.
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')))
Srivastava
sumber
2
Bisakah Anda menjelaskan mengapa solusi Anda lebih baik daripada yang sudah disediakan?
Noel Widmer
Saya tidak mengatakan bahwa solusi saya lebih baik daripada yang lain. Saya hanya memberikan solusi saya untuk melakukan itu.
Srivastava
1

Lihat itertools.combinationsatau itertools.permutations.

Brian Cain
sumber
4
kombinasi tidak relevan dengan masalahnya. dia mengubah huruf, yang berarti keteraturan relevan, yang berarti hanya permutasi
mesin merindukan
1

Berikut adalah versi kode illerucis yang sedikit lebih baik untuk mengembalikan daftar semua permutasi string sdengan karakter berbeda (tidak harus dalam urutan leksikografik), tanpa menggunakan alat itert:

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
Adriano
sumber
1

Namun inisiatif lain dan solusi rekursif. Idenya adalah memilih huruf sebagai poros dan kemudian membuat kata.

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

Keluaran:

abc
acb
bac
bca
cab
cba
Faroq AL-Tam
sumber
0

Ini adalah versi generator yang sangat sederhana:

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)

Saya pikir itu tidak terlalu buruk!

Gritty Kitty
sumber
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
Ritabrata Sanyal
sumber
tolong coba tambahkan beberapa deskripsi.
Arun Vinoth
0

Berikut adalah implementasi rekursif yang sederhana dan langsung;

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
saya menjadi
sumber
1
Anda harus memperbaiki lekukannya. Tidak perlu menyimpan hasil panggilan rekursif ke stringPermutationsdalam daftar - Anda dapat mengulanginya secara langsung, mis for perm in stringPermutations(s[:pos] + s[pos+1:]):. Juga, Anda dapat menyederhanakan forlingkaran dengan menggunakan enumeratebukan range, dan menghilangkan char = s[pos]tugas: 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')]
Satish Kumar
sumber
5
tolong coba tambahkan beberapa deskripsi.
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"))

Ini adalah salah satu cara untuk menghasilkan permutasi dengan rekursi, Anda dapat memahami kode dengan mudah dengan mengambil string 'a', 'ab' & 'abc' sebagai input.

Anda mendapatkan semua N! permutasi dengan ini, tanpa duplikat.

Jasser
sumber
0

Semua orang menyukai bau kode mereka sendiri. Hanya membagikan yang menurut saya paling sederhana:

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
r_2
sumber
0

Program ini tidak menghilangkan duplikat, tetapi menurut saya ini adalah salah satu pendekatan yang paling efisien:

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
Nagaraju Chukkala
sumber
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)
Chandra Sekhar Battini
sumber
tolong coba tambahkan beberapa deskripsi.
Arun Vinoth
0

Solusi yang lebih sederhana menggunakan permutasi.

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)
Nelson Katale
sumber
0

Semua Kemungkinan Kata dengan tumpukan

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

Kembalikan permutasi panjang r elemen yang berurutan dalam iterable.

Jika r tidak ditentukan atau Tidak ada, maka r default ke panjang iterable dan semua kemungkinan permutasi panjang penuh dihasilkan.

Permutasi dipancarkan dalam urutan leksikografik. Jadi, jika input iterable diurutkan, permutasi tupel akan diproduksi dalam urutan yang diurutkan.

Elemen diperlakukan sebagai unik berdasarkan posisinya, bukan nilainya. Jadi jika elemen inputnya unik, tidak akan ada nilai pengulangan di setiap permutasi.

CodePerfectPlus
sumber
0

Ini adalah solusi rekursif n!yang menerima elemen duplikat dalam string

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

Saya memvalidasi solusi dengan mempertimbangkan dua elemen, jumlah kombinasi adalah n!dan hasilnya tidak boleh mengandung duplikat. Begitu:

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

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

Dengan pendekatan rekursif.

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']
Muriithi Derrick
sumber
-1

Dengan Rekursi

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

Dengan pendekatan Iteratif (Menggunakan Stack)

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

Dengan diurutkan secara leksikografis

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