Creo que para solucionar este problema no es necesario ningún bucle. Esta es la solución más simple que he podido encontrar:
from __future__ import division def sumar_multiplos_k(a1, an,d): n = an/d S = ((a1+an)/2)*n return S print(sumar_multiplos_k(3,999,3)+sumar_multiplos_k(5,995,5)-sumar_multiplos_k(15,990,15)) El razonamiento es el siguiente: Viendo la naturaleza del problema, tiene una pinta de progresión aritmética que echa para atrás. Al final es encontrar la suma de los múltiplos de 3 o de 5, es decir, suma de series cuyos elementos están separados entre tres o cinco unidades, es decir, con razón 3 o 5. La expresión de la progresión aritmética es: ((a1+an)/2)*n donde a1 es el primer elemento de la serie, an es el último elemento de la serie y n el número total de elementos. En esta expresión lo único que podemos desconocer es n, el número total de elementos, pero si vamos a la expresión general de la progresión podemos decir que an = a1+(n-1)d donde a1 es el primer elemento, n el número total de elementos y d la razón de la serie, es decir el número que debemos sumar al elemento anterior para conseguir el próximo elemento. De la expresión anterior tenemos todos los parámetros excepto n así que se convierte es simplificar y resolver una ecuación de primer grado. El "quid" de la cuestión, creo yo, es en darse cuenta de lo siguiente: Álgunos múltiplos de 3: 3,6,9,12,15,...,27,30,33,...,42,45,... Algunos múltiplos de 5: 5,10,15,20,25,30,35,40,45,... Si observamos 15,30,45 se repiten en ambas series por lo que si sumasemos ambas progresiones estaríamos sumando los múltiplos de 15 dos veces. Por lo que a la suma de la progresión de 3 y la progresión de 5 hay que restarle la progresión de 15. Y ese sería el resultado. No he encontrado una forma más óptima de hacerlo, de esta forma nos quitamos de encima los bucles y no hay que buscar optimizaciones con cython ni nada parecido. Saludos! On Wed, 5 Sep 2018 at 06:55, AGTUGO <agt...@gmail.com> wrote: > > Después de ver los tiempos de ejecución obviamente aquellos métodos que > hicieron un for pues fueron más lentos, los que generaron los números para > ser sumados pues son los más rápidos, lo cual no es ninguna sorpresa. Creo > que la mayoría de la gente no busca velocidad en python pero hay casos donde > optimizaciones pequeñas hacen la diferencia, al final creo que lo mejor para > optimizar pues es escribir en c o en cython algunas funciones en particular. > Creo que mucho más fácil de mantener en cython. Prepararé una comparación de > todos los métodos aquí expuestos en cPython, pypy, adicionalmente numoy y > cython, para cerrar esta discusión y tratar de llegar a algo que pueda ser > referenciado en el futuro. > > On Tue, Sep 4, 2018 at 10:10 PM AGTUGO <agt...@gmail.com> wrote: >> >> Adicionalmente me gusta verlo como conjuntos A union B. >> >> def euler001_with_sets(n: int, multiples:Tuple[int]) -> int: >> union_set = set() >> all_sums_set = (set(range(0,n,mul)) for mul in multiples) >> union_set = union_set.union(*all_sums_set) >> return sum(union_set) >> >> >> >> On Tue, Sep 4, 2018 at 9:35 AM AGTUGO <agt...@gmail.com> wrote: >>> >>> Aquí lo único que haría para cualquier caso es sacar la comparación en una >>> funciòn para que no este tan hardcoded >>> >>> from typing import List, Tuple >>> >>> begin = 0 >>> end = 1000 >>> multiples= (3,5) >>> >>> """ >>> Esta función revisa si es divisible entre todos los multiplos propuestos >>> dentro del mundo >>> de los naturales y retorna un booleano en caso de que así sea >>> """ >>> def is_divisible(tb_divided:int, multiples: List[int]) -> bool: >>> return any((tb_divided%mul == 0 for mul in multiples)) >>> >>> def euler001(n: int, multiples:Tuple[int]) -> int: >>> return sum(i for i in range(1, n) if is_divisible(i,multiples)) >>> >>> print(euler001(end, multiples)) >>> >>> >>> >>> On Tue, Sep 4, 2018 at 5:33 AM Chema Cortes <pych...@gmail.com> wrote: >>>> >>>> >>>> >>>> El lun., 3 sept. 2018 a las 21:12, AGTUGO (<agt...@gmail.com>) escribió: >>>>> >>>>> """ >>>>> Problema tomado de >>>>> https://projecteuler.net/problem=1 >>>>> >>>>> >>>>> If we list all the natural numbers below 10 that are multiples >>>>> of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23. >>>>> Find the sum of all the multiples of 3 or 5 below 1000. >>>>> >>>>> Si listamos todos los numeros naturales menores a 10 que son >>>>> múltiplos de 3 o 5 obtenemos 2, 5, 6 y 9. La suma de los múltiplos es 23. >>>>> Encuentra la suma de los múltiplos de 3 o 5 menores de 1000. >>>>> >>>>> >>>>> """ >>>>> >>>>> """ >>>>> Este es mi aporte de código no esta diseñado para ser eficiente, >>>>> el objetivo es jugar con el lenguaje. Ojalá puedan compartir >>>>> una visión interesante de como resolver este problema. >>>>> Si tienen una forma más eficiente de hacer el set o más elegante también >>>>> es bienvenido. >>>>> Saludos. >>>>> """ >>>>> >>>>> import itertools >>>>> begin = 0 >>>>> end = 1000 >>>>> multiples= (3,5) >>>>> >>>>> x = [range(begin,end,i) for i in multiples] >>>>> x = sum(set(itertools.chain(*x))) >>>>> >>>>> print(x) >>>>> >>>> >>>> Con este tipo de retos, es interesante que sea lo más simple posible. En >>>> el enunciado sólo pide la suma, no es preciso guardar ninguno de los >>>> resultados intermedios. >>>> >>>> Lo más simple sería: >>>> >>>> def euler001(n: int) -> int: >>>> return sum(i for i in range(1, n) if i%3 == 0 or i%5 ==0) >>>> >>>> ... que es una forma concisa de poner lo que propone agus en otro mensaje. >>>> >>>> Una forma más efectiva, aunque muy poco "escalable" en caso de que fueran >>>> más múltiplos a considerar: >>>> >>>> def euler001(n: int) -> int: >>>> return sum(range(3, n, 3)) + sum(range(5, n, 5)) - sum(range(15, n, >>>> 15)) >>>> >>>> >>>> -- >>>> Hyperreals *R "Quarks, bits y otras criaturas infinitesimales": >>>> https://blog.ch3m4.org >>>> Buscador Python Hispano: http://busca.ch3m4.org >>>> _______________________________________________ >>>> Python-es mailing list >>>> Python-es@python.org >>>> https://mail.python.org/mailman/listinfo/python-es >>> >>> >>> >>> -- >>> Arturo Muñoz Tolosa >> >> >> >> -- >> Arturo Muñoz Tolosa > > > > -- > Arturo Muñoz Tolosa > _______________________________________________ > Python-es mailing list > Python-es@python.org > https://mail.python.org/mailman/listinfo/python-es _______________________________________________ Python-es mailing list Python-es@python.org https://mail.python.org/mailman/listinfo/python-es