2011-08-20 12 views
5

Estoy intentando crear un bucle para generar y cadenas de impresión de la siguiente manera:Generar cadenas alfanuméricas secuencialmente

  1. sólo caracteres alfanuméricos:
  2. 0-9 son antes AZ, az y sometidos a examen,
  3. La longitud sube a 4 caracteres.

lo tanto, sería imprimir:

  1. todas las cadenas de 0-z
  2. luego de 00-zz
  3. luego de 000-zzz
  4. luego desde 0000-zzzz

y luego se detiene.

+0

Es demasiado difícil entender su pregunta ... ¿sería a07z una cadena legal o no? – immortal

+0

Sí. Todas las cadenas alfanuméricas de longitud 1-4 son legales – joseph

+0

Entonces, cuando dices 0-9 antes de A-Z, ¿quieres decir que 0000 debería aparecer antes de A000? – immortal

Respuesta

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) 

Esto primero hace una cadena de todos los números, letras mayúsculas y minúsculas.

Luego, para cada longitud de 1-4, imprime todas las combinaciones posibles de esos números y letras.

tener en cuenta que es un montón de combinaciones - 62^4 + 62^3 + 62^2 + 62.

+0

Esa es una solución genial. También es una buena cosa hacer un generador en lugar de imprimir directamente las cadenas. – Drekembe

+0

Sé que es un montón de combinaciones, principalmente lo hacía solo para fines de prueba. Lo corté en 3 caracteres en lugar de 4 – joseph

+0

Sí, dijo que quería un "lazo que imprimiera las cuerdas", así que eso es lo que le di. – agf

0

No me gusta la respuesta dada ante mí usando product mirando desde su implementación en el pitón documentación parece abarcar toda la cosa en una lista en la memoria antes de comenzar a dar los resultados.

Esto es muy malo para su caso ya que, como él mismo dijo, el número de permutación aquí es enorme (más de un millón). Para este caso, se creó la declaración yield, de modo que las listas enormes pudieran generarse dinámicamente en lugar de distribuirse en la memoria (tampoco me gustó el despilfarrador range donde xrange es perfectamente aplicable).

me gustaría ir para una solución como esta:

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 

De esta manera, todo lo que se extiende en la memoria es una pila recursiva "n" de profundidad, donde "n" es la longitud de sus permutaciones (4 en este caso) y solo se devuelve un solo elemento cada vez.

caracteres es el conjunto de caracteres a elegir, la longitud es 4 y el uso es bastante similar a los productos, excepto que no abarca toda la lista en la memoria durante el tiempo de ejecución.

+2

Dice en la descripción del 'producto' -" Esta función es equivalente al siguiente código, excepto que la implementación real no genera resultados intermedios en la memoria: "Todas las herramientas en' itertools' funcionan de esa manera, es la todo el propósito del módulo. – agf

+0

también, el rango de llamadas (5) derrochador en comparación con xrange es un poco exagerado ... – hop

+0

Creo que para rangos muy pequeños, 'range' es en realidad _less_ derrochador que' xrange'. – agf

0

Lo he codificado hoy. Hace exactamente lo que quiere y más. También es extensible

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