2015-08-17 30 views
5

Próbuję wymyślić sposób generowania wszystkich możliwych unikatowych ciągów znaków z alfabetu 20 znaków, w którym kolejność w ciągu nie ma znaczenia, a długość ciągu może różnią się. Tak więc, na przykład, za sznur o długości 3, możliwych ciągów byłoby AAA, AAB, AAC, itd., Ale nie obejmują BAA lub CAA. Zorientowałem się, używając metody itertools.product(), ale jest to bardzo kosztowne obliczeniowo. Najprostszym sposobem na to jest użycie zagnieżdżonych pętli. Na przykład, aby wygenerować wszystkie ciągi o długości czterech:Zmienna liczba przewidywalnych pętli w języku 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]) 

Teraz można to łatwo zrobić za dowolny ciąg długość przez zmianę liczby pętli. Biorąc pod uwagę, że sama sekwencja pętli for jest dość przewidywalna, czy istnieje sposób na uproszczenie tego kodu, zamiast na wykonanie trzech pętli zamiast if length == 3 i uruchomienie w ten sposób czterech pętli? Jedynym sposobem mogę myśleć to zrobić właśnie teraz jest kilka if-elif stwierdzeń:

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

Czy istnieje łatwiejszy sposób niż tylko obejmujące kilka możliwych wartości długości?

+3

Czy możesz powiedzieć więcej o rozwiązaniu, które podjęło próbę/nie, używając 'itertools.product'? Twoja droga powinna być o wiele bardziej kosztowna obliczeniowo. –

+1

@ Two-BitAlchemist: nie, kod PO jest lepszy, ponieważ generuje tylko te, których potrzebuje. Używając produktu, w czteroliterowym pudełku wyrzuciłbyś 151145/160000 wyników. – DSM

Odpowiedz

3

IIUC, można po prostu użyć 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 

(gdzie orig to po prostu Twój oryginalny kod zawinięty w funkcję).

+0

chciał tylko odpowiedzieć na to samo, produkt dałby zupełnie inne wyjście –

+0

@PadraicCunningham: wtedy nie jestem pewien, czy rozumiem twoje pytanie do komentarza do PO - kod PO jest bardziej wydajny niż produkt, ponieważ generuje tylko te, które on potrzeby, zamiast patrzeć na nie wszystkie i odfiltrować te, których nie chce. – DSM

+0

Początkowo nie przyjrzałem się kodowi OP, zakładałem, że chcą produktu, biorąc pod uwagę, że używali produktu. –

Powiązane problemy