Pablasso

El Proyecto Euler: Problema 1

May 18, 2008

El Proyecto Euler es una serie de problemas de programación. Si quieres enterarte de que va esto, lee la introducción.

Problema 1

Si listamos todos los números naturales debajo de 10 que son múltiplos de 3 o 5, tenemos 3, 5, 6 y 9. La suma de estos múltiplos es 23.

Encuentra la suma de todos los múltiplos de 3 o 5 debajo de 1000.

Este problema lo he visto como de los “recomendados” para poner en las entrevistas para trabajo, simple y rápido, te dice claramente las 3 condiciones a evaluar.

El operador % regresa el residuo de una división, por lo que podemos iterar de uno en uno hasta el límite superior (1000) y verificar si cada número es perfectamente divisible (el residuo es 0) entre 3 o 5, entonces lo podemos almacenar.

Resuelto en C.

    #include 
    
    main()
    {
        int sum = 0, i;
        for ( i = 1; i < 1000; i++ )
        {
            if ( (i % 3 == 0) || (i % 5 == 0) ) {
                sum += i;
            }
        }
    
        printf("El resultado es: %d", sum);
    }

Conclusión

Comparando con resultados del Proyecto Euler, si bien la solución de fuerza bruta que hice no esta mal, si la pregunta exigiera un limite con cantidades grandes no es eficiente hacer un loop comparando resultado por resultado, sino que es mejor calcular las operaciones por separado.

La suma de números divisibles por 3, la suma de números divisibles por 5 y restando finalmente los números divisibles por 15 que sino tendríamos los divisibles comunes de 3 y 5 contados 2 veces. Se puede evadir por completo cualquier loop si utilizamos progresiones aritméticas.

Para poner un poco en contraste, haciendo benchmark (utilizando gprof) de mi solución para el limite de 1 billón (si si, un uno seguido de 9 ceros), este laptop tarda 15.68 segundos.

En cambio la siguiente versión (versión de sandippal en el foro) que utiliza este principio, tarda menos de .01 segundo, ¿bastante no?.

    #include 
    #define NUM 999999999
    
    main()
    {
      unsigned long long mult3  = NUM / 3;
      unsigned long long mult5  = NUM / 5;
      unsigned long long mult15 = NUM / 15;
      unsigned long long sum3, sum5, sum15;
    
      sum3 = 3  * mult3  * (mult3 + 1) / 2;
      sum5 = 5  * mult5  * (mult5 + 1) / 2;
      sum15 = 15 * mult15 * (mult15 + 1) / 2;
    
      printf("resultado: %lld\n", sum3 + sum5 - sum15);
    }

Gracias en especial al comentario de Xiam, grande su explicación.


Juan Pablo OrtizWritten by Juan Pablo Ortiz who lives and works in Guadalajara, Mexico. You should follow him on Twitter