Desafios en JavaScript, ronda 2 | Soluciones

A modo de resumen, expongo en esta entrada algunas de las soluciones a los problemas expuestos en la entrada anterior. En este tema del foro Foros del Web, se pueden ver distintas soluciones volcadas por los usuarios de dicha comunidad.

Problema 1

Escribir una función que reciba un único argumento númerico y devuelva el número romano correspondiente.

Como mi solución no es lo suficientemente elegante, procedo a adjuntar la solución propuesta por @cronos que es valida para numeros menores a 4000:

function romanize(n) {
	var
		values = [1, 5, 10, 50, 100, 500, 1000],
		letras = ['I', 'V', 'X', 'L', 'C', 'D', 'M'],
		res = [],
		num, letra, val, pos, insert

	for(var i = 6; num = values[i], letra = letras[i]; i--) {
		// Suficientemente grande
		if(n / num >= 1) {
			// Número de letras repetidas
			var r = Math.floor(n / num); 

			// Restamos el actual
			n -= r * num; 

			if(r < 4){
				// Metemos las letras
				while(r--){
					res.push(letra);
				}
			} else {
				// No se pueden repetir 4+ veces
				val = res.pop(); // Última letra

				// Si es el string vacío o letra == "M" (no hay anterior)
				// usamos la letra anterior a esta
				pos = (val ? letras.indexOf(val) : i) + 1; 

				// Y si letra == "M" -> letras[pos] no existirá y usamos M
				insert = letra + (letras[pos] || 'M'); 

				// Insertamos el string
				res.push(insert);
			}
		} else {
			// Si no vamos a poner letra usamos un ""
			// para que no afecte pop
			res.push('');
		}
	}

	return res.join('');
}

romanize(18); // "XVIII"

En este jsfiddle se puede encontrar la misma solución.

Problema 2

Escribir una función que reciba un único argumento númerico y devuelva la factorización del mismo.

Este problema fue publicado en la primer entrega de la revista online “Python entre todos“, más precisamente en esta página.

function factorizar(n) {
    var i = 2, res = [];

    // Generamos un mapa ficticio (en realidad es un array), de forma
    // numero -> cantidad de apariciones
    while(i <= n) {
        if(n%i && i++) continue;

        n = n/i;
        res[i] = res[i] || 0;
        res[i]++;
    }

    // Convertimos el array a un array de strings
    return res.reduce(function(memo, current, index) {
        memo.push(
            // Verificamos si es potencia
            index + (current > 1 ? '^' + current : '')
        );
        return memo;
    }, []).join(' x '); // Y finalmente contatenamos
}

factorizar(992); // "2^5 x 31"

Esta solución puede probarse en este jsfiddle.

Problema 3

Escribir una función que ordene una lista (array) de números enteros sin usar condicionales. Al igual que la entrega anterior, consideramos condicionales a las sentencias operadores booleanos, if, switch, operador ternario, try/catch.

Este problema fue propuesto en un thread del foro 3DGames, por el usuario ‘El Hombre Gris‘.

Para seguir la onda comunitaria (y ya que nuevamente mi solución no era lo suficientemente elegante) adjunto la solución de @panino5001, que es una simple y eficaz implementación del quicksort en la cual reemplaza el swap por una asignación bastante particular. Esta solución puede encontrarse en este jsfiddle.

function quicksort(arr){
	var opts, o, temp, piv;

 	while(arr.length){
		opts = [[],[]];
		piv = arr[0];
		temp = [].concat(arr.slice(1));

		while(temp.length){
			var o = temp.shift();

			// Inserta el elemento en el head o en el tail segun
			// corresponda
			opts[+Boolean(( o - piv).toString().indexOf('-'))].push(o);
		}
		return quicksort(opts[0]).concat(piv, quicksort(opts[1]));
	}

	return [];
}

quicksort([1, 2, 1, 4, -3, 8, 1, 9]); // [-3, 1, 1, 1, 2, 4, 8, 9]


Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Comment

You may use these tags : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>