python for-loop nested

Python: anidados ''para'' bucles



for-loop nested (5)

Me gustaría repasar todos los números de n dígitos, de modo que el segundo dígito del número siempre sea inferior o igual al primero, el tercero sea inferior o igual al segundo, etc. Puedo obtener esto escribiendo un código horrible como:

for i in range(10): for j in range(i+1): for k in range(j+1):

etc., pero con números de 10 dígitos, mi código se ve horrible, y eso también es mucha escritura, y la sangría se vuelve horrible si quiero felicitar a algunos de ellos. ¿Hay una forma agradable y concisa de conseguir esto?

Edición: solo para que la gente sepa por qué me molesto con esto, https://projecteuler.net/problem=74 me hace verificar los números de 1 a 1 millón. Desafortunadamente, no es tan sencillo como pensaba: los números con ceros a la izquierda se tratan de manera diferente a los que tienen ceros en el interior, por lo que hubo que realizar algo de magia adicional. De todos modos, gracias a todos por sus sugerencias perspicaces.


Este es un enfoque usando itertools :

from itertools import combinations_with_replacement N = 3 for kji in combinations_with_replacement((str(i) for i in range(10)), N): print(''''.join(reversed(kji)))

tenga en cuenta que el orden no es el mismo que en su enfoque original.

Hace poco tuve una pregunta similar ...


Implementé la sugerencia de @ iFlo como se comentó originalmente. No es muy eficiente, pero ciertamente no lleva años.

def digit_test(n): while n > 9: if (n % 100 / 10) < (n % 10): return False n /= 10 return True # under a second to construct a list of all numbers below 1000000 meeting the criteria candidates = [x for x in xrange(1,1000000) if digit_test(x)] # should be 8001 elements, consistent with other algorithms print len(candidates)


Podría usar itertools :

>>> for comb in itertools.combinations_with_replacement(range(9, -1, -1), 3): print comb (9, 9, 9) (9, 9, 8) (9, 9, 7) (9, 9, 6) ... (4, 0, 0) (3, 3, 3) (3, 3, 2) (3, 3, 1) (3, 3, 0) (3, 2, 2) (3, 2, 1) (3, 2, 0) (3, 1, 1) (3, 1, 0) (3, 0, 0) (2, 2, 2) (2, 2, 1) (2, 2, 0) (2, 1, 1) (2, 1, 0) (2, 0, 0) (1, 1, 1) (1, 1, 0) (1, 0, 0) (0, 0, 0)

O recursivamente, agregando más y más dígitos hasta que sean suficientes, lo que puede producir más directamente objetos int lugar de tuplas de dígitos (no estoy seguro de si eso es lo que realmente necesita):

def build(enough, prefix=0): if prefix >= enough: print(prefix) return for digit in range(prefix % 10 + 1) if prefix else range(1, 10): build(enough, prefix * 10 + digit)

Demostración (tenga en cuenta que omite " 000 ", no estoy seguro de si desea eso):

>>> n = 3 >>> build(10**(n-1)) 100 110 111 200 210 211 220 221 222 300 310 311 320 321 322 330 331 332 333 400 410 411 420


Probablemente implementaría esto recursivamente:

def generate(max, digits): for d in range(max + 1): if digits == 1: yield d else: first = d * 10**(digits-1) for n in generate(d, digits - 1): yield first + n

La salida:

In : list(generate(3, 3)) Out: [0, 100, 110, 111, 200, 210, 211, 220, 221, 222, 300, 310, 311, 320, 321, 322, 330, 331, 332, 333]


Un enfoque recursivo simple:

def ordered_digits_generator(numDigits,min=1,max=9): for first in range(min,max+1): if numDigits == 1: yield first else: addend = first*10**(numDigits-1) for rest in ordered_digits(numDigits-1,min=0,max=first): yield addend+rest

Luego se llama a través de:

for number in ordered_digits_generator(10): print number

Funciona como se espera.

El enfoque del matemático.

El paquete itertools ya tiene una lógica que esencialmente ya implementa esta recursión. Presumiblemente mejor que nosotros, con pruebas significativas. Así que podemos usarlo de la siguiente manera:

import itertools def ordered_digits_combo(numDigits): exponent = [10**i for i in range(0,numDigits)] for subset in itertools.combinations(range(0,numDigits+9),numDigits): if subset[numDigits-1]>numDigits-1: v = 0 for i in range(0,numDigits): v += exponent[i]*(subset[i]-i) yield v

Dado un subconjunto ordenado a[0]<a[1]<...<a[n-1] de {0,1,...,n+8} , seleccionamos el número con el i dígito de la derecho igual a a[i]-i . Tenemos que excluir el caso a[n-1]==n-1 porque consiste en el número con todos los ceros.