順次

2011-08-20 5 views
5

次のように私が生成するループを作成しようと印刷文字列だ英数字の文字列を生成します。順次

  1. 英数字のみ:
  2. 0-9、AZの前にあるAZ、前
  3. です
  4. 長さは最大4文字になります。

そこで、それが印刷う:

  1. すべての文字列を0-zから
  2. 次いで00-ZZ
  3. から次いで
  4. 次いで000-ZZZから0000-ZZZZから

停止します。

+0

あなたの質問を理解するのは難しいです... a07zは合法的な文字列であるかどうか? – immortal

+0

はい。すべて英数字の文字列の長さ1〜4は有効です – joseph

+0

0-9がA-Zの前にあるとすると、0000はA000の前に来るはずですか? – immortal

答えて

17
from string import digits, ascii_uppercase, ascii_lowercase 
from itertools import product 

chars = digits + ascii_uppercase + ascii_lowercase 

for n in range(1, 4 + 1): 
    for comb in product(chars, repeat=n): 
     print ''.join(comb) 

これは、最初にすべての数字、大文字、および小文字の文字列を作成します。

次に、1-4の長さごとに、それらの数字と文字の可能な組み合わせをすべて表示します。

これは組み合わせのLOTである点に注意してください - 62^4 + 62^3 + 62^2 + 62

+0

それはクールな解決策です。また、すばらしいことは、文字列を直接印刷するのではなく、ジェネレータにすることです。 – Drekembe

+0

私はそれがたくさんの組み合わせであることを知っています。私は主にテスト目的のためにそれをやっていました。私は4文字の代わりに3文字に切り捨てた – joseph

+0

ええ、彼は "文字列を印刷したループ"を私が彼に捧げたものにしたいと言った。 – agf

0

pythonでその実装を見て以来、私はproductを使用して私の前に与えられた答えを嫌いますそれは結果を出す前にメモリ内のリストに全体を広げているように見えます。

これはagf自身が言ったように、ここでの順列の数は膨大で(百万をはるかに上回っている)、これはあなたのケースにとって非常に悪いことです。この場合、yieldステートメントが作成されました。その結果、巨大なリストがメモリに広がっているのではなく動的に生成されるようになりました(無駄なrangexrangeが完全に当てはまりませんでした)。

私はこのようなソリューションのために行くだろう:「n」は、あなたの順列の長さである深い

def generate(chars, length, prefix = None): 
    if length < 1: 
     return 
    if not prefix: 
     prefix = '' 
    for char in chars: 
     permutation = prefix + char 
     if length == 1: 
      yield permutation 
     else: 
      for sub_permutation in generate(chars, length - 1, prefix = permutation): 
       yield sub_permutation 

この方法では、メモリにまたがることすべてが、再帰的なスタックである「n」は、(4この場合は1回だけ返されます)。

charsは、長さが4であり、実行時にメモリ内のリスト全体にまたがっていない点を除けば、使用方法は製品に似ています。

+2

これは 'product'の説明で - "この関数は次のコードと同等ですが、実際の実装では中間結果がメモリに蓄積されません。 "itertoolsのすべてのツールはそのように機能します。モジュール全体の目的。 – agf

+0

また、xrangeと比較して無駄な呼び出し範囲(5)は伸びのビットです... – hop

+0

非常に小さな範囲では、 'range'は実際に' xrange'よりも無駄です。 – agf

0

私は本日このコードを作成しました。それはあなたが欲しいものを正確に行います以上。それも拡張可能です

def lastCase (lst): 
    for i in range(0, len(lst)): 
     if (lst[i] != '_'): 
      return False 
    return True 


l = [''] * 4 #change size here if needed. I used 4 
l[0] = '0' 
index = 0 

while (not lastCase(l)): 

    if (ord(l[index]) > ord('_')): 
     l[index] = '0' 
     index += 1 
     while(l[index] == '_'): 
      l[index] = '0' 
      index += 1 
     if (l[index] == ''): 
      l[index] = '0' 

    #print or process generated string 
    print(''.join(l)) 

    l[index] = chr(ord(l[index]) +1) 

    if (ord(l[index]) > ord('9') and ord(l[index]) < ord('A')): 
     l[index] = 'A' 
    elif (ord(l[index]) > ord('Z') and ord(l[index]) < ord('_') ): 
     l[index] = '_' 

    index = 0 

print (''.join(l))