2010-10-26 13 views
5

He escrito un programa para comprobar si mi pensamiento sobre la solución en papel es correcto (y lo es).Simplifique este código python

La tarea: cuántos ceros se encuentra en la parte posterior de la multiplicación de todos los números de 10 a 200.

Es 48 y es un sencillo de calcular manualmente.

Nunca escriba en pitón en serio y esto es lo que me pasa:

mul = 1 
for i in range(10, 200 + 1): 
    mul *= i 

string = str(mul) 
string = string[::-1] 
count = 0; 
for c in str(string): 
    if c == '0': 
     count += 1 
    else: 
     break 

print count 
print mul 

apuesto a que es posible escribir la misma más elegante en un lenguaje como una pitón.

PS: Sí, se trata de una tarea, pero no la mía - me ayudó a un chico ;-)

Respuesta

11

Una aplicación recta de avance que no implica calcular el factorial (para que funcione con números grandes, es decir, 2000000) (editado):!

fives = 0 
twos = 0 
for i in range(10, 201): 
    while i % 5 == 0: 
     fives = fives + 1 
     i /= 5 
    while i % 2 == 0: 
     twos = twos + 1 
     i /= 2 
print(min(fives, twos)) 
+0

Sería bueno si pudiera descubrir cómo funciona. –

+3

Cuenta el número de cinco y dos en la factorización prima del factorial de forma iterativa (¡entonces 10! Tendría 2 cincos y ocho doses). Como 5 * 2 = 10, y ningún otro número primo se puede multiplicar por 10, el número de 10 en la factorización (que es el número de ceros finales) es el mínimo de la cantidad de cincos y el número de dos en el primo factorización. El número de cincos y de dos es mucho más pequeño que el factorial calculado. – irrelephant

+3

Aunque la pregunta sí requiere 10-200, este es definitivamente un mejor enfoque para números mucho más grandes. Para números más pequeños, hacer la multiplicación resulta ser más rápido (al menos cuando ejecuté pruebas timeit). – snapshoe

3
import itertools 
mul = reduce(lambda x,y: x*y, range(10, 200+1)) 
zeros = itertools.takewhile(lambda s: s == "0", reversed(str(mul))) 
print len(list(zeros)) 

La segunda línea calcula el producto, el tercer obtiene un iterador de todos los ceros a la derecha en ese número, el último imprime el número de esos ceros.

+2

podría sustituir 'lambda x, y: x * y' con' 'Y operator.mul' –

+0

range' con' xrange' (aunque sería menor en este caso) –

+0

@Brendan Long: ya que siempre ys itera desde el comienzo hasta el final del rango - ¿no 'xrange' una sobrecarga? – zerkms

3
len(re.search('0*$', str(reduce(lambda x, y: x*y, range(10, 200 + 1),1))).group(0)) 
+4

Eso es un feo Python ... –

+1

pero es hermoso si te gusta el funcional programación, ojo del espectador y todo! –

+3

No diría que esto es muy funcional. No ves muchas expresiones regulares en la programación funcional. –

6
import math 

answer = str(math.factorial(200)/math.factorial(9)) 
count = len(answer) - len(answer.rstrip('0')) 
  1. importar la biblioteca de matemáticas
  2. Calcular la factorial de 200 y se llevan los primeros 9 números
  3. Gaza distancia ceros a la derecha y averiguar la diferencia de longitudes
+0

Lo más lacónico en este momento – zerkms

+0

No 'reduciría (operator.mul, xrange (10, 200 + 1))' ¿Sería más eficiente que los factoriales + división? –

+0

@Brendan Long: todas las respuestas son apreciadas, pero comprobaré la más elegante ;-P – zerkms

0
mul = str(reduce(lambda x,y: x*y, xrange(10, 201))) 
count = len(mul) - len(mul.rstrip("0")) 
2

¿Se refiere a ceros? Lo que es nulo de lo contrario?

¿Algunas matemáticas no lo simplificarían?

Cuántos 5s en 200 se len ([x para x en el rango (5, 201, 5)]) = 40

Cuántos 25s en 200 se len ([x para x en el rango (25, 201, 5) si x% 25 == 0]) = 8

Cuantos 125s en 200 son len ([x para x en el rango (120, 201, 5) si x% 125 == 0]) = 1

5s totales = 49

200! = 5^2^49 * 49 * (otros números no divisibles por 2 o 5)

por lo que hay 49 ceros

+0

Para ser claro, es 48, no 49 ;-) Y lo resolví manualmente de la misma manera. La pregunta actual es solo una curiosidad acerca de cómo escribir el algoritmo de "fuerza bruta" en python. – zerkms

+0

@zerkms: supongo que ya debes haber hecho eso. ¡Tonto de mí! – pyfunc

4
print sum(1 + (not i%25) + (not i%125) for i in xrange(10,201,5))