martes, 20 de julio de 2010

Combos Anidados con JQuery

Hay muchas maneras de crear combos anidados a través de javascript (ajax), aunque muchas veces necesitamos hacerlo de manera eficiente. Aqui propongo una manera donde los combos se cargan rápidamente a través de un servicio Json. El ejemplo tipico es elegir un Estado geográfico y que al seleccionarlo aparezcan las Ciudades asociadas a este Estado.

Lo primero que hacemos es crear el servicio del lado del servidor, donde el código quedaría mas o menos asi:

archivo: "./servicios/json.getCiudades.php"

// Conectarse a la base de datos

$option='[';
if($_GET['id'] && is_numeric($_GET['id'])) {
$result=mysql_query("select id_ciudad,nombre_ciudad from ciudades where id_estado='".$_GET['id']."'");
if($result && mysql_num_rows($result)>0) {
$error = false;
while ($row = mysql_fetch_array($result))
{
$option.= '{ "valor": "'.$row[0].'", "texto": "'.$row[1].'"}, ';
}
$option = substr( $option , 0, -2);
}
mysql_close();
}
$option=$option.']';
header('Content-Type: text/html; charset=ISO-8859-1');
echo($option);


Tambien podriamos utilziar una función de PHP llamada json_encode() para convertir un objeto directamente al formato JSON, sin embargo las primeras versiones de PHP no disponen nativamente de esta función. La razón de utilizar JSON es que puede ser convertido directamente en un objeto de javascript a través de una evaluación directa en el código.

Del lado del cliente, crearemos dos combos llamados ciudad y estado, de esta manera:


< html>...
< body>...
< form>...
< select name="estado" id="estado>< /select>
< select name="ciudad" id="estado>< /select>
< /form>
< /body>
< /html>


Luego incrustamos un bloque JQUERY para poder generar las ciudades dependientes del Estado seleccionado. Lo podriamos insertar directamente despues de la etiqueta body o donde sea mas cómodo. El código quedaría de esta manera:


< script type="text/javascript">
$(function() {
$("select#estado").change(function(){
$.ajax({
url: "./servicios/json.getCiudades.php?id=" + $(this).val(),
type: "GET",
dataType: "json",
error: function() {
alert("hay un error en el servicio de datos");
return false;
},
success: function(j) {
var opciones = '';
for (var i = 0; i < j.length; i++)
opciones += '';
$("#ciudad").html(opciones);
}
});
});

});
< /script>


Y listo!, con este código estamos invocando al script en PHP que trae las ciudades según el código de estado y las renderizamos directamente del lado del cliente dentro del combo ciudades. Observarán que la formación del combo de ciudades es casi instantáneo.

jueves, 1 de julio de 2010

Numeros primos en Java

Los números primos a lo largo del tiempo ha sido una de las ramas más complejas de la matemática. Poseen muchas aplicaciones prácticas debido a sus propiedades de números verdaderamente "únicos", asi como es el caso de la criptografía asimétrica por ejemplo. Pero uno de los problemas que ha tenido la humanidad desde sus inicios es determinar una función eficiente que genere estos números con un bajo costo computacional. Aqui escribo 5 versiones de funciones para cálcular números primos, en orden de rapidez y con un algoritmo que se encarga de medir el tiempo de ejecucion para numeros relativamente grandes.


public class Main {
private static long tiempomin=0;
private static int ganador = -1;

public static class Cronometro {
long t0;
public Cronometro() {
t0 = System.currentTimeMillis();
}
public long Parar() {
return (System.currentTimeMillis()-t0);
}
}

public static boolean esPrimo1(long n) {
if(n < 2) return false;
if(n < 4) return true;
for (long i = 2; i <= n; i++) if (n%i == 0) return false;
return true;
}

public static boolean esPrimo2(long n) {
if(n < 2) return false;
if(n < 4) return true;
for (long i = 2; i <= (long) Math.sqrt(n); i++) if (n%i == 0) return false;
return true;
}

public static boolean esPrimo3(long n) {
if(n< 2) return false;
if(n< 4) return true;
for (long i = 2; i*i <= n; i++) if (n%i == 0) return false;
return true;
}

public static boolean esPrimo4(long n) {
long nPrueba;
long nLimite;
if(n%2==0) return false;
nPrueba = 3;
nLimite = n;
while(nLimite > nPrueba) {
if(n%nPrueba==0) return false;
nLimite = n/nPrueba;
nPrueba += 2;
}
return true;
}

public static void Invocar(int nFuncion, long max) {
long enc=0;
if(ganador< 0) System.out.println("Se inicia el conteo para n=" + max + "...");
Cronometro reloj = new Cronometro();
long t2=0;
switch(nFuncion) {
case 1: for(long i=0; i <= max; i++) if(esPrimo1(i)) enc++; break;
case 2: for(long i=0; i <= max; i++) if(esPrimo2(i)) enc++; break;
case 3: for(long i=0; i <= max; i++) if(esPrimo3(i)) enc++; break;
case 4: for(long i=0; i <= max; i++) if(esPrimo4(i)) enc++; break;
}
t2 = reloj.Parar();
if(tiempomin==0 || t2< tiempomin) { tiempomin = t2; ganador = nFuncion; }
System.out.println("esPrimo" + nFuncion + "(1..n) " + t2 + " ms (" + enc + " numeros primos encontrados)");
}

public static void main(String[] args) {
int nfunciones = 4;
long maximo = 6000000;
for(int i=2; i <= nfunciones; i++) Invocar(i,maximo);
System.out.println("La funcion ganadora es esPrimo" + ganador + "() con " + tiempomin + " ms!!");
}

}