2008/10/21

Cómo NO calcular el mínimo común múltiplo con JavaScript

Esto es un descargo de ignorancia. Básicamente me escarmiento públicamente a mi mismo para ver si no vuelvo a repetir algo que he hecho y que no me gusta por que no está bien.

Antes de continuar, la excusa es que tengo las mates tan olvidadas, que podrían darme de palos y no me iban a sacar nada de nada. De hecho me saltó la alarma "YOU'RE DOING IT WRONG!!!" cuando vi lo que empezaba a tardar el tema, pero entre las (pocas) mates y el sueño no mejoré demasiado el asunto.

Ahora el delito, que es calcular el MCM (de los números del 1 al 20 en este caso) tal que así:

const LIMIT = 20;
var store = [1];
var test = 0;
while( store.join('')!=0 ){
    store = [];
    test++ ;
    for(var i=2; i< LIMIT; i++){
        store.push( test%i );
        if( test%i!=0 ) break;
    }
}

El problema, principalmente, es el rato que tarda en pasearse por los números hasta que encuentra el resultado. A parte de la caminata desde el 0 hasta algo después del 232*10^6 calculando restos de división (que no es una operación precisamente de las más ágiles), tiene un par de tonterías por el medio:

  • el doble casting en el while: de array a string con el join, y de string a numérico en la comparación (y tiro por que me toca);
  • y la linea del break: que por un lado intenta ahorrarse unas pocas iteraciones precisamente en el bucle menos significativo, y por otro lado vuelve a gastar recursos calculando el mismo resto de la linea que está justo arriba.

Aunque puestos a ver el lado bueno de las cosas, al menos no es mucho código (y el número del resultado es el correcto).

Por si alguien quiere probarlo en su navegador, le recomiendo que desactive el aviso sobre scripts atascados (creo que en firefox está en el about:config por max_script_runtime; en safari se desactiva desde el menú de debug [que no es visible por defecto pero en la red hay sobradas instrucciones para hacerlo]).

PD: Ya podría JavaScript tener alguna función matemática más, que el objeto global Math es más escaso que el guardarropa de tarzán (apenas tiene un puñado de constantes y no muchas más funciones a parte de las trignométricas, se le ve escaso)

PPD: El MCM es un problema de la página del proyecto Euler, que tiene un puñado gordo de problemas para repasar mates y programación.

3 comentarios:

  1. Hola, yo también estoy tratando de resolver este problema. Si llego a alguna conclusión te comento.

    ResponderEliminar
  2. He encontrado esto
    Function MCD(a,b)
    {
    Var resto,aux;
    If(a < b)
    {
    aux=a;
    a=b;
    b=aux;
    }
    If ((a%b)==0) resto=b;
    While((a%b)!=0)
    {
    resto=a%b;
    a=b;
    b=resto;
    }
    Return resto;
    }

    y para sacar el mcm llamas de la siguiente forma mcm = (x*y)/MCD(x,y) lo saque de aquí www.videoaprende.com/manuales/javascript.pdf
    espero que te sirva saludos.

    ResponderEliminar
  3. Bueno, la solución me la dio precisamente ese método tan lento del apunte (mal no está, sólo es lento).

    Luego, el foro del problema en la página del proyecto Euler vi lo que estaba haciendo mal: fallo en las mates básicas, no en la programación (si me hubiera dado cuenta de lo que estaban pidiendo --matemáticamente hablando-- no habría hecho lo que hice que, si te das cuenta, es bastante literal según el enunciado del problema :)

    De todos modos gracias por los comentarios :)

    ResponderEliminar

Nota: solo los miembros de este blog pueden publicar comentarios.