Come generare tutte le permutazioni di un elenco?


592

Come si generano tutte le permutazioni di un elenco in Python, indipendentemente dal tipo di elementi in tale elenco?

Per esempio:

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]

5
Sono d'accordo con la risposta ricorsiva e accettata - OGGI. Tuttavia, questo è ancora un grande problema di informatica. La risposta accettata risolve questo problema con complessità esponenziale (2 ^ NN = len (elenco)) Risolvilo (o dimostra che non puoi) in tempo polinomiale :) Vedi "Problema del commesso viaggiatore"
FlipMcF,

38
@FlipMcF Sarà difficile "risolverlo" in tempo polinomiale, dato che ci vuole tempo fattoriale anche solo per enumerare l'output ... quindi no, non è possibile.
Thomas

Risposte:


489

A partire da Python 2.6 (e se siete su Python 3) si ha uno standard libreria di strumento per questo: itertools.permutations.

import itertools
list(itertools.permutations([1, 2, 3]))

Se stai usando un vecchio Python (<2.6) per qualche motivo o sei solo curioso di sapere come funziona, ecco un bel approccio, preso da http://code.activestate.com/recipes/252178/ :

def all_perms(elements):
    if len(elements) <=1:
        yield elements
    else:
        for perm in all_perms(elements[1:]):
            for i in range(len(elements)):
                # nb elements[0:1] works in both string and list contexts
                yield perm[:i] + elements[0:1] + perm[i:]

Un paio di approcci alternativi sono elencati nella documentazione di itertools.permutations. Eccone uno:

def permutations(iterable, r=None):
    # permutations('ABCD', 2) --> AB AC AD BA BC BD CA CB CD DA DB DC
    # permutations(range(3)) --> 012 021 102 120 201 210
    pool = tuple(iterable)
    n = len(pool)
    r = n if r is None else r
    if r > n:
        return
    indices = range(n)
    cycles = range(n, n-r, -1)
    yield tuple(pool[i] for i in indices[:r])
    while n:
        for i in reversed(range(r)):
            cycles[i] -= 1
            if cycles[i] == 0:
                indices[i:] = indices[i+1:] + indices[i:i+1]
                cycles[i] = n - i
            else:
                j = cycles[i]
                indices[i], indices[-j] = indices[-j], indices[i]
                yield tuple(pool[i] for i in indices[:r])
                break
        else:
            return

E un altro, basato su itertools.product:

def permutations(iterable, r=None):
    pool = tuple(iterable)
    n = len(pool)
    r = n if r is None else r
    for indices in product(range(n), repeat=r):
        if len(set(indices)) == r:
            yield tuple(pool[i] for i in indices)

14
Questa e altre soluzioni ricorsive hanno un potenziale rischio di consumare tutta la RAM se l'elenco permutato è abbastanza grande
Boris Gorelik,

3
Essi hanno inoltre raggiungono il limite di ricorsione (e morire) con grandi liste
dbr

58
bgbg, dbr: sta usando un generatore, quindi la stessa funzione non consumerà memoria. Ti rimane su come consumare l'iteratore restituito da all_perms (supponi che potresti scrivere ogni iterazione su disco e non preoccuparti della memoria). So che questo post è vecchio ma lo sto scrivendo a beneficio di tutti coloro che lo leggono ora. Anche ora, il modo migliore sarebbe usare itertools.permutations () come sottolineato da molti.
Jagtesh Chadha,

18
Non solo un generatore. Sta usando generatori nidificati, ognuno dei quali cede alla precedente nello stack di chiamate, nel caso non fosse chiaro. Usa la memoria O (n), che è buona.
cdunn2001,

1
PS: l'ho risolto, con for i in range(len(elements))invece di for i in range(len(elements)+1). In effetti, l'elemento individuato elements[0:1]può trovarsi in len(elements)posizioni diverse, nel risultato no len(elements)+1.
Eric O Lebigot,

339

E in Python 2.6 in poi:

import itertools
itertools.permutations([1,2,3])

(restituito come generatore. Utilizzare list(permutations(l))per tornare come elenco.)


15
Funziona anche in Python 3
quando il

10
Si noti che esiste un rparametro, ad esempio itertools.permutations([1,2,3], r=2), che genererà tutte le possibili permutazioni selezionando 2 elementi:[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
toto_tico

278

Il seguente codice SOLO con Python 2.6 e versioni successive

Innanzitutto, importa itertools:

import itertools

Permutazione (l'ordine conta):

print list(itertools.permutations([1,2,3,4], 2))
[(1, 2), (1, 3), (1, 4),
(2, 1), (2, 3), (2, 4),
(3, 1), (3, 2), (3, 4),
(4, 1), (4, 2), (4, 3)]

Combinazione (l'ordine NON ha importanza):

print list(itertools.combinations('123', 2))
[('1', '2'), ('1', '3'), ('2', '3')]

Prodotto cartesiano (con diversi iterabili):

print list(itertools.product([1,2,3], [4,5,6]))
[(1, 4), (1, 5), (1, 6),
(2, 4), (2, 5), (2, 6),
(3, 4), (3, 5), (3, 6)]

Prodotto cartesiano (con uno iterabile e se stesso):

print list(itertools.product([1,2], repeat=3))
[(1, 1, 1), (1, 1, 2), (1, 2, 1), (1, 2, 2),
(2, 1, 1), (2, 1, 2), (2, 2, 1), (2, 2, 2)]


`print list (itertools.permutations ([1,2,3,4], 2)) ^` SyntaxError: sintassi non valida` Ho appena iniziato a usare VS Code Cosa ho fatto di sbagliato? Il puntatore punta sotto la "t" di "list"
gus

39
def permutations(head, tail=''):
    if len(head) == 0: print tail
    else:
        for i in range(len(head)):
            permutations(head[0:i] + head[i+1:], tail+head[i])

chiamato come:

permutations('abc')

Perché stampare la coda e quindi restituire None? Perché non restituire invece la coda? Perché non restituire nulla comunque?
bugmenot123,

30
#!/usr/bin/env python

def perm(a, k=0):
   if k == len(a):
      print a
   else:
      for i in xrange(k, len(a)):
         a[k], a[i] = a[i] ,a[k]
         perm(a, k+1)
         a[k], a[i] = a[i], a[k]

perm([1,2,3])

Produzione:

[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 2, 1]
[3, 1, 2]

Mentre sto scambiando il contenuto dell'elenco è richiesto un tipo di sequenza mutabile come input. Ad esempio perm(list("ball"))funzionerà e perm("ball")non funzionerà perché non puoi cambiare una stringa.

Questa implementazione di Python si ispira all'algoritmo presentato nel libro Computer Algorithms di Horowitz, Sahni e Rajasekeran .


Presumo che k sia la lunghezza o le permutazioni. Per k = 2 uscite [1, 2, 3]. Non dovrebbe essere (1, 2) (1, 3) (2, 1) (2, 3) (3, 1) (3, 2) ??
Konstantinos Monachopoulos,

k è l'indice dell'elemento che si desidera scambiare
sf8193

22

Questa soluzione implementa un generatore, per evitare di conservare tutte le permutazioni in memoria:

def permutations (orig_list):
    if not isinstance(orig_list, list):
        orig_list = list(orig_list)

    yield orig_list

    if len(orig_list) == 1:
        return

    for n in sorted(orig_list):
        new_list = orig_list[:]
        pos = new_list.index(n)
        del(new_list[pos])
        new_list.insert(0, n)
        for resto in permutations(new_list[1:]):
            if new_list[:1] + resto <> orig_list:
                yield new_list[:1] + resto

16

In uno stile funzionale

def addperm(x,l):
    return [ l[0:i] + [x] + l[i:]  for i in range(len(l)+1) ]

def perm(l):
    if len(l) == 0:
        return [[]]
    return [x for y in perm(l[1:]) for x in addperm(l[0],y) ]

print perm([ i for i in range(3)])

Il risultato:

[[0, 1, 2], [1, 0, 2], [1, 2, 0], [0, 2, 1], [2, 0, 1], [2, 1, 0]]

15

Il codice seguente è una permutazione sul posto di un determinato elenco, implementato come generatore. Poiché restituisce solo riferimenti all'elenco, l'elenco non deve essere modificato all'esterno del generatore. La soluzione non è ricorsiva, quindi utilizza poca memoria. Funziona bene anche con più copie di elementi nell'elenco di input.

def permute_in_place(a):
    a.sort()
    yield list(a)

    if len(a) <= 1:
        return

    first = 0
    last = len(a)
    while 1:
        i = last - 1

        while 1:
            i = i - 1
            if a[i] < a[i+1]:
                j = last - 1
                while not (a[i] < a[j]):
                    j = j - 1
                a[i], a[j] = a[j], a[i] # swap the values
                r = a[i+1:last]
                r.reverse()
                a[i+1:last] = r
                yield list(a)
                break
            if i == first:
                a.reverse()
                return

if __name__ == '__main__':
    for n in range(5):
        for a in permute_in_place(range(1, n+1)):
            print a
        print

    for a in permute_in_place([0, 0, 1, 1, 1]):
        print a
    print

15

Un modo abbastanza ovvio secondo me potrebbe anche essere:

def permutList(l):
    if not l:
            return [[]]
    res = []
    for e in l:
            temp = l[:]
            temp.remove(e)
            res.extend([[e] + r for r in permutList(temp)])

    return res

11
list2Perm = [1, 2.0, 'three']
listPerm = [[a, b, c]
            for a in list2Perm
            for b in list2Perm
            for c in list2Perm
            if ( a != b and b != c and a != c )
            ]
print listPerm

Produzione:

[
    [1, 2.0, 'three'], 
    [1, 'three', 2.0], 
    [2.0, 1, 'three'], 
    [2.0, 'three', 1], 
    ['three', 1, 2.0], 
    ['three', 2.0, 1]
]

2
Mentre produce tecnicamente l'output desiderato, stai risolvendo qualcosa che potrebbe essere O (n lg n) in O (n ^ n) - "leggermente" inefficiente per grandi set.
James,

3
@James: Sono un po 'confuso da O (n log n) che tu dai: il numero di permutazioni è n !, che è già molto più grande di O (n log n); quindi, non riesco a vedere come una soluzione potrebbe essere O (n log n). Tuttavia, è vero che questa soluzione è in O (n ^ n), che è molto più grande di n !, come risulta dall'approssimazione di Stirling.
Eric O Lebigot,

9

Ho usato un algoritmo basato sul sistema numerico fattoriale - Per un elenco di lunghezza n, è possibile assemblare ogni permutazione elemento per elemento, selezionando tra gli elementi rimasti in ogni fase. Hai n scelte per il primo elemento, n-1 per il secondo e solo uno per l'ultimo, quindi puoi usare le cifre di un numero nel sistema numerico fattoriale come indici. In questo modo i numeri da 0 a n! -1 corrispondono a tutte le possibili permutazioni in ordine lessicografico.

from math import factorial
def permutations(l):
    permutations=[]
    length=len(l)
    for x in xrange(factorial(length)):
        available=list(l)
        newPermutation=[]
        for radix in xrange(length, 0, -1):
            placeValue=factorial(radix-1)
            index=x/placeValue
            newPermutation.append(available.pop(index))
            x-=index*placeValue
        permutations.append(newPermutation)
    return permutations

permutations(range(3))

produzione:

[[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]

Questo metodo non è ricorsivo, ma è leggermente più lento sul mio computer e xrange genera un errore quando n! è troppo grande per essere convertito in un intero lungo C (n = 13 per me). Era abbastanza quando ne avevo bisogno, ma non sono itertools.permutations da un colpo lungo.


3
Ciao, benvenuto in Stack Overflow. Sebbene pubblicare il metodo della forza bruta abbia i suoi meriti, se non pensi che la tua soluzione sia migliore della soluzione accettata, probabilmente non dovresti pubblicarla (specialmente su una vecchia domanda che ha già così tante risposte).
Hannele,

1
In realtà stavo cercando un approccio non bibliotecario a forza bruta, quindi grazie!
Jay Taylor,

8

Si noti che questo algoritmo ha una n factorialcomplessità temporale, dove si ntrova la lunghezza dell'elenco di input

Stampa i risultati in fuga:

global result
result = [] 

def permutation(li):
if li == [] or li == None:
    return

if len(li) == 1:
    result.append(li[0])
    print result
    result.pop()
    return

for i in range(0,len(li)):
    result.append(li[i])
    permutation(li[:i] + li[i+1:])
    result.pop()    

Esempio:

permutation([1,2,3])

Produzione:

[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]

8

Si può davvero iterare sul primo elemento di ogni permutazione, come nella risposta di Tzwenn. È comunque più efficiente scrivere questa soluzione in questo modo:

def all_perms(elements):
    if len(elements) <= 1:
        yield elements  # Only permutation possible = no permutation
    else:
        # Iteration over the first element in the result permutation:
        for (index, first_elmt) in enumerate(elements):
            other_elmts = elements[:index]+elements[index+1:]
            for permutation in all_perms(other_elmts): 
                yield [first_elmt] + permutation

Questa soluzione è circa il 30% più veloce, apparentemente grazie alla ricorsione che termina al len(elements) <= 1posto di 0. È anche molto più efficiente in termini di memoria, in quanto utilizza una funzione di generatore (attraverso yield), come nella soluzione di Riccardo Reyes.


6

Questo si ispira all'implementazione di Haskell usando la comprensione dell'elenco:

def permutation(list):
    if len(list) == 0:
        return [[]]
    else:
        return [[x] + ys for x in list for ys in permutation(delete(list, x))]

def delete(list, item):
    lc = list[:]
    lc.remove(item)
    return lc

6

Implementazione regolare (nessun rendimento - farà tutto in memoria):

def getPermutations(array):
    if len(array) == 1:
        return [array]
    permutations = []
    for i in range(len(array)): 
        # get all perm's of subarray w/o current item
        perms = getPermutations(array[:i] + array[i+1:])  
        for p in perms:
            permutations.append([array[i], *p])
    return permutations

Implementazione del rendimento:

def getPermutations(array):
    if len(array) == 1:
        yield array
    else:
        for i in range(len(array)):
            perms = getPermutations(array[:i] + array[i+1:])
            for p in perms:
                yield [array[i], *p]

L'idea di base è di andare su tutti gli elementi dell'array per la 1a posizione, quindi in 2a posizione andare su tutti gli altri elementi senza l'elemento scelto per la 1a, ecc. Puoi farlo con ricorsione , dove il i criteri di arresto stanno arrivando a una matrice di 1 elemento, nel qual caso si restituisce quella matrice.

inserisci qui la descrizione dell'immagine


Questo non funziona per me _> ValueError: gli operandi non possono essere trasmessi insieme alle forme (0,) (2,) , per questa linea:perms = getPermutations(array[:i] + array[i+1:])
RK1

@ RK1 qual è stato l'input?
David Refaeli,

Sto passando in un numpyarray _> getPermutations(np.array([1, 2, 3])), vedo che funziona per un elenco, mi sono appena confuso perché l'arg di funzioni è array:)
RK1

@ RK1 sono contento che funzioni :-) L'elenco è una parola chiave in Python, quindi di solito non è una buona idea chiamare il tuo parametro una parola chiave, poiché lo "oscurerà". Quindi uso l'array di parole, poiché questa è l'effettiva funzionalità dell'elenco che sto usando - il loro modo di fare array. Immagino che se scriverei la documentazione la chiarirei. Inoltre credo che le domande basilari di "intervista" debbano essere risolte senza pacchetti esterni, come numpy.
David Refaeli,

Ahah è vero, sì, stavo cercando di usarlo numbae sono diventato avido di velocità, quindi ho cercato di usarlo esclusivamente con numpyarray
RK1

4

Per prestazioni, una soluzione insensibile ispirata a Knuth , (p22):

from numpy import empty, uint8
from math import factorial

def perms(n):
    f = 1
    p = empty((2*n-1, factorial(n)), uint8)
    for i in range(n):
        p[i, :f] = i
        p[i+1:2*i+1, :f] = p[:i, :f]  # constitution de blocs
        for j in range(i):
            p[:i+1, f*(j+1):f*(j+2)] = p[j+1:j+i+2, :f]  # copie de blocs
        f = f*(i+1)
    return p[:n, :]

La copia di grandi blocchi di memoria consente di risparmiare tempo: è 20 volte più veloce di list(itertools.permutations(range(n)):

In [1]: %timeit -n10 list(permutations(range(10)))
10 loops, best of 3: 815 ms per loop

In [2]: %timeit -n100 perms(10) 
100 loops, best of 3: 40 ms per loop

3
from __future__ import print_function

def perm(n):
    p = []
    for i in range(0,n+1):
        p.append(i)
    while True:
        for i in range(1,n+1):
            print(p[i], end=' ')
        print("")
        i = n - 1
        found = 0
        while (not found and i>0):
            if p[i]<p[i+1]:
                found = 1
            else:
                i = i - 1
        k = n
        while p[i]>p[k]:
            k = k - 1
        aux = p[i]
        p[i] = p[k]
        p[k] = aux
        for j in range(1,(n-i)/2+1):
            aux = p[i+j]
            p[i+j] = p[n-j+1]
            p[n-j+1] = aux
        if not found:
            break

perm(5)

3

Ecco un algoritmo che funziona su un elenco senza creare nuovi elenchi intermedi simili alla soluzione di Ber all'indirizzo https://stackoverflow.com/a/108651/184528 .

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

Puoi provare il codice qui: http://repl.it/J9v


3

La bellezza della ricorsione:

>>> import copy
>>> def perm(prefix,rest):
...      for e in rest:
...              new_rest=copy.copy(rest)
...              new_prefix=copy.copy(prefix)
...              new_prefix.append(e)
...              new_rest.remove(e)
...              if len(new_rest) == 0:
...                      print new_prefix + new_rest
...                      continue
...              perm(new_prefix,new_rest)
... 
>>> perm([],['a','b','c','d'])
['a', 'b', 'c', 'd']
['a', 'b', 'd', 'c']
['a', 'c', 'b', 'd']
['a', 'c', 'd', 'b']
['a', 'd', 'b', 'c']
['a', 'd', 'c', 'b']
['b', 'a', 'c', 'd']
['b', 'a', 'd', 'c']
['b', 'c', 'a', 'd']
['b', 'c', 'd', 'a']
['b', 'd', 'a', 'c']
['b', 'd', 'c', 'a']
['c', 'a', 'b', 'd']
['c', 'a', 'd', 'b']
['c', 'b', 'a', 'd']
['c', 'b', 'd', 'a']
['c', 'd', 'a', 'b']
['c', 'd', 'b', 'a']
['d', 'a', 'b', 'c']
['d', 'a', 'c', 'b']
['d', 'b', 'a', 'c']
['d', 'b', 'c', 'a']
['d', 'c', 'a', 'b']
['d', 'c', 'b', 'a']

3

Questo algoritmo è il più efficace, evita il passaggio di array e la manipolazione nelle chiamate ricorsive, funziona in Python 2, 3:

def permute(items):
    length = len(items)
    def inner(ix=[]):
        do_yield = len(ix) == length - 1
        for i in range(0, length):
            if i in ix: #avoid duplicates
                continue
            if do_yield:
                yield tuple([items[y] for y in ix + [i]])
            else:
                for p in inner(ix + [i]):
                    yield p
    return inner()

Uso:

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

(1, 2, 3)
(1, 3, 2)
(2, 1, 3)
(2, 3, 1)
(3, 1, 2)
(3, 2, 1)

3
def pzip(c, seq):
    result = []
    for item in seq:
        for i in range(len(item)+1):
            result.append(item[i:]+c+item[:i])
    return result


def perm(line):
    seq = [c for c in line]
    if len(seq) <=1 :
        return seq
    else:
        return pzip(seq[0], perm(seq[1:]))

3

UN ALTRO APPROCCIO (senza librerie)

def permutation(input):
    if len(input) == 1:
        return input if isinstance(input, list) else [input]

    result = []
    for i in range(len(input)):
        first = input[i]
        rest = input[:i] + input[i + 1:]
        rest_permutation = permutation(rest)
        for p in rest_permutation:
            result.append(first + p)
    return result

L'input può essere una stringa o un elenco

print(permutation('abcd'))
print(permutation(['a', 'b', 'c', 'd']))

Questo non funziona per un elenco con numeri interi, ad es. [1, 2, 3]ritorni[6, 6, 6, 6, 6, 6]
RK1

@ RK1, puoi provare questoprint(permutation(['1','2','3']))
Tatsu

Grazie che funziona
RK1

3

Disclaimer: plug informe per autore del pacchetto. :)

Il pacchetto trotter è diverso dalla maggior parte delle implementazioni in quanto genera pseudo elenchi che in realtà non contengono permutazioni ma piuttosto descrivono mappature tra permutazioni e rispettive posizioni in un ordinamento, rendendo possibile lavorare con 'elenchi' molto grandi di permutazioni, come mostrato in questa demo che esegue operazioni e ricerche piuttosto istantanee in una pseudo-lista 'contenente' tutte le permutazioni delle lettere dell'alfabeto, senza usare più memoria o elaborazione rispetto a una tipica pagina web.

In ogni caso, per generare un elenco di permutazioni, possiamo fare quanto segue.

import trotter

my_permutations = trotter.Permutations(3, [1, 2, 3])

print(my_permutations)

for p in my_permutations:
    print(p)

Produzione:

Una pseudo-lista contenente 6 3-permutazioni di [1, 2, 3].
[1, 2, 3]
[1, 3, 2]
[3, 1, 2]
[3, 2, 1]
[2, 3, 1]
[2, 1, 3]

2

Genera tutte le possibili permutazioni

Sto usando python3.4:

def calcperm(arr, size):
    result = set([()])
    for dummy_idx in range(size):
        temp = set()
        for dummy_lst in result:
            for dummy_outcome in arr:
                if dummy_outcome not in dummy_lst:
                    new_seq = list(dummy_lst)
                    new_seq.append(dummy_outcome)
                    temp.add(tuple(new_seq))
        result = temp
    return result

Casi test:

lst = [1, 2, 3, 4]
#lst = ["yellow", "magenta", "white", "blue"]
seq = 2
final = calcperm(lst, seq)
print(len(final))
print(final)

2

Per farti risparmiare ore e ore di ricerche e sperimentazioni, ecco la soluzione di permutaioni non ricorsive in Python che funziona anche con Numba (a partire dalla versione 0.41):

@numba.njit()
def permutations(A, k):
    r = [[i for i in range(0)]]
    for i in range(k):
        r = [[a] + b for a in A for b in r if (a in b)==False]
    return r
permutations([1,2,3],3)
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]

Per dare un'idea delle prestazioni:

%timeit permutations(np.arange(5),5)

243 µs ± 11.1 µs per loop (mean ± std. dev. of 7 runs, 1 loop each)
time: 406 ms

%timeit list(itertools.permutations(np.arange(5),5))
15.9 µs ± 8.61 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
time: 12.9 s

Quindi usa questa versione solo se devi chiamarla dalla funzione njitted, altrimenti preferisci l'implementazione itertools.


1

Vedo molta iterazione in corso all'interno di queste funzioni ricorsive, non esattamente pura ricorsione ...

quindi per quelli di voi che non riescono a rispettare nemmeno un singolo ciclo, ecco una soluzione grossolana, totalmente inutile e completamente ricorsiva

def all_insert(x, e, i=0):
    return [x[0:i]+[e]+x[i:]] + all_insert(x,e,i+1) if i<len(x)+1 else []

def for_each(X, e):
    return all_insert(X[0], e) + for_each(X[1:],e) if X else []

def permute(x):
    return [x] if len(x) < 2 else for_each( permute(x[1:]) , x[0])


perms = permute([1,2,3])

1

Un'altra soluzione:

def permutation(flag, k =1 ):
    N = len(flag)
    for i in xrange(0, N):
        if flag[i] != 0:
            continue
        flag[i] = k 
        if k == N:
            print flag
        permutation(flag, k+1)
        flag[i] = 0

permutation([0, 0, 0])

0

La mia soluzione Python:

def permutes(input,offset):
    if( len(input) == offset ):
        return [''.join(input)]

    result=[]        
    for i in range( offset, len(input) ):
         input[offset], input[i] = input[i], input[offset]
         result = result + permutes(input,offset+1)
         input[offset], input[i] = input[i], input[offset]
    return result

# input is a "string"
# return value is a list of strings
def permutations(input):
    return permutes( list(input), 0 )

# Main Program
print( permutations("wxyz") )

0
def permutation(word, first_char=None):
    if word == None or len(word) == 0: return []
    if len(word) == 1: return [word]

    result = []
    first_char = word[0]
    for sub_word in permutation(word[1:], first_char):
        result += insert(first_char, sub_word)
    return sorted(result)

def insert(ch, sub_word):
    arr = [ch + sub_word]
    for i in range(len(sub_word)):
        arr.append(sub_word[i:] + ch + sub_word[:i])
    return arr


assert permutation(None) == []
assert permutation('') == []
assert permutation('1')  == ['1']
assert permutation('12') == ['12', '21']

print permutation('abc')

Output: ['abc', 'acb', 'bac', 'bca', 'cab', 'cba']


0

utilizzando Counter

from collections import Counter

def permutations(nums):
    ans = [[]]
    cache = Counter(nums)

    for idx, x in enumerate(nums):
        result = []
        for items in ans:
            cache1 = Counter(items)
            for id, n in enumerate(nums):
                if cache[n] != cache1[n] and items + [n] not in result:
                    result.append(items + [n])

        ans = result
    return ans
permutations([1, 2, 2])
> [[1, 2, 2], [2, 1, 2], [2, 2, 1]]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.