2015-08-17 18 views
5

Sto provando a creare un modo per generare tutte le stringhe univoche possibili da un alfabeto di 20 caratteri in cui l'ordine all'interno della stringa non ha importanza e la lunghezza della stringa può variare. Ad esempio, per una stringa di lunghezza 3, le stringhe possibili potrebbero essere AAA, AAB, AAC, ecc., Ma non includere BAA o CAA. Ho trovato un modo usando itertools.product(), ma è molto costoso dal punto di vista computazionale. Il modo più semplice per farlo è semplicemente l'uso di cicli annidati. Per esempio, per generare tutti stringhe di lunghezza quattro:Numero variabile prevedibile per loop in Python

alphabet = ["A","C","D","E","F","G","H","I","K","L", 
      "M","N","P","Q","R","S","T","V","W","Y"] 
combos = [] 
for a in range(len(alphabet)): 
    for b in range(a,len(alphabet)): 
     for c in range(b,len(alphabet)): 
      for d in range(c,len(alphabet)): 
       combos.append(alphabet[a] + alphabet[b] + alphabet[c] + alphabet[d]) 

Ora, questo può facilmente essere fatto per qualsiasi stringa di lunghezza cambiando il numero di cicli for. Dato che la sequenza loop for è di per sé abbastanza prevedibile, c'è un modo per semplificare questo codice anziché avere if length == 3 eseguire tre per loop e if length == 4 eseguire quattro loop invece? L'unico modo che posso pensare di farlo in questo momento è un po 'di if-elif dichiarazioni:

if length == 3: 
    for a in range(len(alphabet)): 
     for b in range(a,len(alphabet)): 
      for c in range(b,len(alphabet)): 
       combos.append(alphabet[a] + alphabet[b] + alphabet[c]) 
elif length == 4: 
    for a in range(len(alphabet)): 
     for b in range(a,len(alphabet)): 
      for c in range(b,len(alphabet)): 
       for d in range(c,len(alphabet)): 
        combos.append(alphabet[a] + alphabet[b] + alphabet[c] + alphabet[d]) 

C'è un modo più facile che solo copre una serie di possibili valori di lunghezza?

+3

Puoi dire di più sulla tua soluzione tentata/fallita usando 'itertools.product'? La tua strada dovrebbe essere molto più dispendiosa dal punto di vista computazionale. –

+1

@ Two-BitAlchemist: no, il codice dell'OP è migliore, perché genera solo quelli di cui ha bisogno. Usando il prodotto, nel caso di 4 lettere, dovresti buttare via 151145/160000 dei risultati. – DSM

risposta

3

IIUC, si può semplicemente utilizzare itertools.combinations_with_replacement .

>>> list(map(''.join, combinations_with_replacement(["a","b","c"],2))) 
['aa', 'ab', 'ac', 'bb', 'bc', 'cc'] 
>>> list(map(''.join, combinations_with_replacement(["a","b","c"],3))) 
['aaa', 'aab', 'aac', 'abb', 'abc', 'acc', 'bbb', 'bbc', 'bcc', 'ccc'] 
>>> list(map(''.join, combinations_with_replacement(alphabet,4))) == orig(alphabet) 
True 

(dove orig è semplicemente il vostro codice originale avvolto in una funzione).

+0

stava per rispondere allo stesso modo, il prodotto avrebbe dato un'uscita completamente diversa –

+0

@PadraicCunningham: quindi non sono sicuro di capire la tua domanda di commento all'OP: il codice dell'OP è più efficiente del prodotto perché genera solo quelli che ha bisogni, piuttosto che guardarli tutti e filtrare quelli che non desidera. – DSM

+0

Inizialmente non ho guardato il codice dell'OP, presumo che volevano il prodotto considerando che stavano usando il prodotto –