:::: MENU ::::

PHP: true vs 1

Muchos habréis oído la típica frase de «utiliza 1 en lugar de true, es más óptimo».
Pues no… ¿pero sí?

Vamos a explicarlo. En primer lugar, imaginemos que hacemos algo tan simple como:

<?php
if(true) {}

Esto per se sería más rápido que:

<?php
if(1) {}

Os preguntaréis el porqué, la respuesta es sencilla; si nosotros le proporcionamos un booleano, este es el tipo que espera recibir, por lo que no tiene que realizar ningún tipo de conversión.

Para corroborarlo, hice un benchmark de la siguiente forma:

<?php
while(true) {
    $startTime = round(microtime(true) * 1000);
    for($i = 0; $i < 200000000; $i++)
        if(1) {}
    $endTime = round(microtime(true) * 1000) - $startTime;
    echo '1: ', $endTime, "ms \n";
    file_put_contents('1.txt', $endTime . "\n", FILE_APPEND);
    
    $startTime = round(microtime(true) * 1000);
    for($i = 0; $i < 200000000; $i++)
        if(true) {}
    $endTime = round(microtime(true) * 1000) - $startTime;
    echo 'true: ', $endTime, "ms \n";
    file_put_contents('true.txt', $endTime . "\n", FILE_APPEND);
}

El resultado fue que, efectivamente, utilizar true en lugar de 1 es más eficiente tal y como se ve a continuación:

Eje X: Iteración // Eje Y: milisegundos (menos es mejor)

En el resultado observamos claramente que true, como predecimos, es más eficiente, en concreto, de media un 12% más eficiente que 1.

¿A qué se debe?
Al no recibir un tipo booleano, tiene que convertir de entero a booleano. PHP comprueba el valor del entero, si este es igual a 0, será false, de lo contrario, true; dicha operación es poco costosa, pero si se repite muchas veces puede llegar a suponer un incremento del tiempo de carga.

Por insignificante que parezca, programar de forma óptima es esencial para grandes compañías que reciben millones de peticiones al día, pues a la larga, cada pequeño detalle suma, y eso puede suponer grandes cantidades de dinero en costes.

La forma más eficiente de hacerlo por nuestra parte es hacer un cast, es decir:

<?php
$int = 1; // 1
$bool = (boolean) $int; // true

No obstante, hay otra forma ligeramente más ineficiente de hacerlo, pero de nuevo, más corta, la doble negación.
Sabemos que si negamos un entero, lo va a convertir a booleano tal y como hemos descrito para después sacar su contrario. Ahora, si negamos el resultado de eso, obtendremos el resultado de la conversión inicial, ya que anulamos la primera negación:

<?php
$int = 1; // 1
$boolOnce = !$int; // false
$boolTwice = !!$int; // true

No obstante…
Hemos hablado de que es más óptimo, pero… ¿en la práctica es así?
Como sabréis, PHP es un lenguaje interpretado y por ende, cada vez que tiene que ejecutar algo tiene que leer el archivo de principio a fin (excepto si utilizamos herramientas como HHVM de Facebook, en cuyo caso todo lo que viene a continuación queda invalidado).

Para ser justos con la gente que argumenta que utilizar 1 es más óptimo al ser interpretado, he querido hacer un benchmark en el cual lee la parte de ‘if(true o 1)’ cada vez:

<?php
while(true) {
    $startTime = round(microtime(true) * 1000);
    for($i = 0; $i < 500000; $i++)
        eval(file_get_contents('read1.php'));
    $endTime = round(microtime(true) * 1000) - $startTime;
    echo '1: ', $endTime, "ms \n";
    file_put_contents('1-ev.txt', $endTime . "\n", FILE_APPEND);
    
    $startTime = round(microtime(true) * 1000);
    for($i = 0; $i < 500000; $i++)
        eval(file_get_contents('readtrue.php'));
    $endTime = round(microtime(true) * 1000) - $startTime;
    echo 'true: ', $endTime, "ms \n";
    file_put_contents('true-ev.txt', $endTime . "\n", FILE_APPEND);
}

He aquí los resultados:

Eje X: Iteración // Eje Y: milisegundos (menos es mejor)

Aunque en el gráfico parezca que ‘1’ gana a ‘true’ por goleada, nada más lejos de la realidad, ‘1’ tan solo gana por un 0,51% de media en más de mil resultados.

En conclusión, dado que PHP es interpretado, es susceptible a que pequeños detalles de este estilo le afecten en su rendimiento. No podemos concluir que ‘1’ sea mejor que ‘true’, o viceversa, pues dependerá del caso.
PHP tiene muchísimas posibilidades, no tan solo podemos desarrollar una web, en cuyo caso, al tener que leer el archivo, utilizaríamos ‘1’; también podemos programar algo que se ejecute en consola, o algo que tenga muchas iteraciones, en cuyo caso sería mejor ‘true’.

Personalmente siempre utilizaría true, son necesarias pocas iteraciones para que sea rentable utilizarlo y considero que hacer que convierta de entero a booleano por detrás es una mala práctica; prueba de ello es que en lectura solo hay un 0,5% de diferencia y en iteración gana ‘true’ con más de un 12% de ventaja.
Finalmente, ‘true’ es más legible, y así está diseñado el lenguaje.


Calcular PI con lanzamientos

¿Nunca has escuchado que se puede calcular PI de forma aproximada con granos de arroz?

Pues muchas de esas formas de calcular PI de forma aproximada se pueden realizar programáticamente, ya que al fin y al cabo se basan en el azar y en la colocación en un plano de elementos.

Para esto, nosotros vamos a utilizar «agujas» (o cualquier elemento que tenga dicha forma, ya sean palillos u otro que queramos imaginar).

¿Por qué agujas? La fórmula que utilizamos es derivada de La aguja de Buffon, acerca de la cual os dejo un artículo interesante:
http://www.estadisticaparatodos.es/taller/buffon/buffon.html

¡Vamos a ello!
Se nos dice que, si tenemos un plano dividido en filas del mismo alto que el tamaño de unas simples agujas, siendo esas divisiones marcadas con lápiz, y lanzamos una cantidad N de agujas sobre ese plano, con la cantidad de colisiones entre las agujas y las líneas marcadas N’ y una simple fórmula obtendremos aproximadamente PI.

A todo esto y aplicando la lógica, no hace falta decir que a mayor número de intentos, mayor «precisión» obtendremos, siempre sabiendo que es imposible obtener el número exacto, y más sabiendo que tiene infinitos decimales.

La fórmula que nos proporcina La aguja de Buffon es la siguiente:

 π = 2N/N'
Siendo
N los lanzamientos totales
N' la cantidad de colisionens

Por tanto, teniendo dicha fórmula, nos ponemos manos a la obra y obtenemos dicho código (PHP):

<?php
// Config
$times = 1000000; // Lanzamientos de aguja
$size = 30; // Tamaño de aguja
$lines = 40; // Cantidad de líneas
$separation = $size; // Separación entre líneas (tiene que ser igual al tamaño)

$gridsize = $lines * $separation;

$count = 0;

for($i = 0; $i < $times; $i++)
{
	// Generamos aguja
	$position = rand(0, $gridsize);
	$angle = rand(0, 90);
	
	// Detectamos las líneas de arriba y abajo (nos ahorramos generar un tablero y recorrerlo en busca de colisiones)
	$upper = floor($position / $separation) * $separation;
	$bottom = ceil($position / $separation) * $separation;
	
	// Borde arriba y abajo de la aguja
	$up = $position - sin(deg2rad($angle)) * $size/2;
	$down = $position + sin(deg2rad($angle)) * $size/2;
	
	if($up <= $upper || $down >= $bottom)	// Si tocan o pasan por encima...
		$count++;							// Sumamos 1 al contador
	
	// Para debuggear:
	// echo 'Pos: ', $position, ' | a: ', $angle, ' | Upper: ', $upper, ' | Bottom: ', $bottom, ' | Up: ', $up, ' | Down: ', $down, "\n";
}

echo 'Colisiones: ', $count, '/', $times, "\n";

// Calculemos PI
echo 'PI = ', 2*$times/$count; // Aplicamos la fórmula

while(true){} // Mantengamos la consola abierta para ver el Output

Como siempre, aquí os dejo el enlace a paste.bin:
https://pastebin.com/KtFpbYVa

Y con simplemente con este trocito de código, habremos aproximado PI de forma casera. Cuanto más aumentemos $times, más cerca de 3,14 estará el resultado.

Os recomiendo también ir probando con otros tamaños de agujas o cantidad de líneas, puede ser que varíe el resultado, pese a que la teoría indique que no.

Aquí podemos ver 2 resultados de prueba:
633840/1000000 colisiones // PI = 3.1553704404897
632918/1000000 colisiones // PI = 3.1599670099444
No son lo más preciso del mundo, pero nos puede valer :)

Y con esto, ¡me despido y os deseo una feliz semana!


La evolución: Local Storage & Session Storage

¡Hola programadores!
Como ya dije hace un tiempo, me niego a poner el cartelito de las cookies, pero bueno, luego en la práctica no es para nada necesario y en realidad… si os quedáis hasta abajo, veréis que en este tema, no influye.

Sea como fuere, no vengo a hablar de esto, si no de la evolución de la web. Y es que Local Storage y Session Storage (aunque personalmente desprecio completamente la segunda), nos permite ver hacia dónde apunta el desarrollo web, y es que estas no pueden ser accedidas por el servidor.

¿Qué significa esto?
Muy fácil: así como las cookies son accedidas por el servidor, normalmente, ya que se mandan junto a las cabeceras, para controlar el logueo de los usuarios; el Local Storage, que no es más que un objeto en JavaScript en el cual podemos guardar strings, u objetos (si contamos que podemos hacer uso de funciones como stringify o parse de JSON), que es almacenado en el navegador al igual que las cookies, no puede ser leído ni se envía mediante las cabeceras al servidor.
Esto último implica que tenemos que usar JavaScript sí o sí para poder interactuar con dichos objetos, de esa forma esto marca una tendencia hacia tener un cliente que muestra la web a base de pequeños datos, como pueden ser objetos JSON, XML (que ya va quedando obsoleto…) u otros métodos como la utilización de node.js, en lugar de que sea el servidor que pre-procese el HTML añadiéndole el contenido.
Obviamente con cookies ya se podía hacer esto, permitiendo además que el servidor leyera directamente de ellas la información que necesitaba para identificar al usuario, pero que las nuevas tecnologías como es LocalStorage apunten a evitarlo, implica y marca una tendencia a seguir.

¿Es mejor?
En caso de usar node.js/websockets, no nos va a afectar, puesto que podíamos leer las cookies desde JavaScript con el objeto docmuent.cookie, pero eso reduce en un pequeñísimo porcentaje la carga de la web, puesto que no tiene que enviar las cookies mediante las cabeceras.
Si usamos PHP puro, podemos olvidarnos, pero lo que sí que podemos hacer, al igual que antes (solo que ahora creando la necesidad implícita de transferir los tokens de las sesiones mediante el método get o post en una petición ajax, y siendo esto una práctica que utilizan servicios como Habbo Hotel para cargar, por ejemplo, las notícias) es enviar con ajax, como he mencionado anteriormente, una petición al servidor, adjuntando también un token, y que este nos devuelva todos los datos necesarios para la web, que además serán colocados con JavaScript.
Con esto último, reduciremos considerablemente el tiempo de carga de nuestra web, o como mínimo el de repuesta del servidor, ya que una vez servido el HTML y los scripts por primera vez, no necesitaremos obtenerlo de nuevo para cambiar su contenido, puesto que podremos hacerlo con solo obtener objetos JSON (u otras maneras) y reemplazando el contenido de elementos por otros, como por ejemplo un campo de nombre de usuario.
No solo, además, podremos cambiar solo el contenido en cuanto a texto, sino que podremos también cambiar el HTML, implicando así que podremos cargar páginas distintas en una sola página, y gracias a funciones como ‘location.pathname.replace’, podremos incluso cambiar la dirección en la barra de direcciones, de forma que si un usuario copia un link al visualizar una foto y se lo pasa a otra persona, podremos cargar la foto directamente al cargar la página (como ya hace twitter o facebook).

Por supuesto, para proyectos pequeños en los cuales la carga del servidor no sea tan importante (ya que obviamente la diferencia será de milisegundos, y que si solo se ve una página será contraproducente), no necesitamos usar dicha nueva tecnología, que además de ser más tediosa y larga a la hora de desarrollar, también aumenta la carga en el navegador, mucho más que una simple página estática en HTML puro, de forma que si hacemos un pequeño blog o una web de empresa, con ni tan solo un millón de visitas mensual, no recomiendo hacerlo bajo ningún concepto.

Entonces… ¿Cookies o LocalStorage?
Fácil, como he aclarado en el párrafo anterior, según el tamaño del proyecto, cargar el cliente en exceso y/o si la carga del servidor no importa, usar LocalStorage es contraproducente. En cambio, si es un gran proyecto como Twitter o Facebook, entonces, usar el cliente como base para cargar toda la web puede ser la mejor opción. Por ende, yo usaría cookies si queremos tirar de servidor y LocalStorage si de JavaScript va la película.
A excepción de si usamos PHP, entonces usar LocalStorage no vale la pena del todo, de cualquier forma vamos a transferir los datos al servidor mediante cabeceras (ojo, si que nos puede servir para controlar qué datos le enviamos, y además, recordemos que si los datos son sensibles o solo se requieren para el funcionamiento temporal de la web, puede ser mejor usar LocalStorage).
Y sí, eso último que acabo de decir se hace posible con LocalStorage, pues este nos permitirá almacenar parámetros como el color de fondo que preferimos u otros detalles (incluso que pueden ser asignados por el servidor al iniciar sesión) y así no tener que cargarlos cada vez, reduciendo una petición al servidor por cambio/carga nueva de página.

Por ende, y contando que cada uno tiene sus pros y sus contras y que no nos vamos a saltar el cartelito de las cookies (puesto que este también es regulado por la famosa ‘ The Cookie Law’), va a depender del caso el hecho de usar uno u otro.

Para los que reclamen por la seguridad: ambos son IGUAL de seguros en cuanto a que el cliente los puede leer y modificar con tan solo la consola JavaScript, pero las cookies se enviarán al servidor en las cabeceras, mientras que el LocalStorage/SessionStorage permanece en el navegador si no lo enviamos nosotros con JavaScript.

Espero que os haya servido de ayuda esta pequeña reflexión.
¡Un saludo a todos!


Ensaïmada numérica, el bot que las resuelve

Pues sí queridos amigos,
Un año y medio después he vuelto y os traigo el post que tanto prometí.
En este caso se trata de un pequeño proyecto de PHP que resuelve las ensaïmadas numéricas (sí, con diéresis, que por algo estamos en Mallorca).
Una ensaïmada numérica es un circuito Hamiltoniano, matemáticamente hablando. En este caso es una tabla de 10×10 en cuyas celdas encontramos todos los valores del 1 al 100 ordenados de una forma específica.
Para empezar, colocamos el valor ‘1’ en cualquiera de las celdas que tiene la tabla, sin importar ningún factor, puro azar. A posteriori, tenemos que proseguir rellenando la tabla incrementando de uno en uno el valor que tenemos, y podemos ir distribuyéndolo de forma diagonal, horizontal y vertical, es decir, podemos ir rellenando hacia arriba, abajo, los lados y diagonal, pero siempre dejando un espacio en diagonal y dos en horizontal o vertical, de forma que sería: 1xx2 (siendo x espacios libres), o en diagonal solo uno. No vale «rebotar» o «atravesar» las paredes, y si deja de haber posiciones libres, no se puede continuar, simplemente hay que empzar con una tabla nueva (o volver atrás en la actual).

Para resolver este problema he optado por fuerza bruta y puro azar en vez de recursividad por pura pereza, pero es posible hacerlo con recursividad, y de hecho no sería demasiado difícil (así que… probablemente tendréis el proyecto modificado en un futuro).

Este programa ha sido realizado en PHP, y se recomienda abrir tantas instancias de este como núcleos/hilos tenga el procesador, para acelerar el proceso. En un futuro os lo traeré en C# y/o Java y con multithreading, de forma que podréis ahorraros el trabajo de abrir múltiples instancias.

Para que funcione, debéis crear una carpeta llamada ‘soluciones’ en la raíz del programa y dentro crear un archivo llamado ‘ultima.txt’. En dicha carpeta se guardarán las soluciones en formato HTML con tablas.

Aquí tenéis un ejemplo de ensaïmada numérica generada por el programa:

Resultado al azar del programa

Resultado al azar del programa

He aquí el código (pastebin también disponible): 

<?php
/* Hecho por Martín Durán - www.maduranma.com */

echo "Buscando soluciones...\n";
$tries = 0;
while(true)
{
// Todos los números a 0 (para tener algo, si no ya se borrará)
for($d = 1; $d <= 100; $d++)
	$r[$d] = 0;
 
// ¿Dónde ponemos el 1?
$tries++;
$rs = rand(1,100);
$r[$rs] = 1;
$l = $rs; // Definimos que la última posición es dónde está el uno, hasta un futuro muy cercano
 
$can_move = true; // Para que el while continue

while($can_move)
{
	// Obtenemos el número de posición horizontal
	if(strlen($l) > 1)
		$h = (substr($l, -1) == 0) ? 10 : substr($l, -1);
	else
		$h = $l;
       
	// Obtenemos el número según el vertical
	if(strlen($l) > 1)
		if($l == 100)
			$v = 10;
		else
			$v = ($h == 10) ? substr($l, 0, 1) : substr($l, 0, 1) + 1;
	else
		$v = 1;
       
	// Ponemos que todos los valores del array $m sean true, para comprobarlos luego
	for($c = 1; $c <= 8; $c++)
		$m[$c] = 1;
       
	// --- Movimientos horizontales ---
	if($h == 8 || $h == 9 || $h == 10 || (($l + 3 > 100) ? true : ($r[$l + 3] != 0)))
		$m[1] = 0;
       
	if($h == 1 || $h == 2 || $h == 3 || (($l - 3 < 1) ? true : ($r[$l - 3] != 0)))
		$m[5] = 0;
       
	// --- Movimientos verticales ---
	if($v == 8 || $v == 9 || $v == 10 || (($l + 30 > 100) ? true : ($r[$l + 30] != 0)))
		$m[3] = 0;
	       
	if($v == 1 || $v == 2 || $v == 3 || (($l - 30 < 1) ? true : ($r[$l - 30] != 0)))
		$m[7] = 0;
	       
	// --- Movimiento arriba derecha ---
	if($h == 9 || $h == 10 || $v == 1 || $v == 2 || (($l - 18 < 1) ? true : ($r[$l - 18] != 0)))
		$m[8] = 0;
	       
	// --- Movimiento arriba izquierda ---
	if($h == 1 || $h == 2 || $v == 1 || $v == 2 || (($l - 22 < 1) ? true : ($r[$l - 22] != 0)))
		$m[6] = 0;
       
	// --- Movimiento abajo derecha ---
	if($h == 9 || $h == 10 || $v == 9 || $v == 10 || (($l + 22 > 100) ? true : ($r[$l + 22] != 0)))
		$m[2] = 0;
       
	// --- Movimiento abajo izquierda ---
	if($h == 1 || $h == 2 || $v == 9 || $v == 10 || (($l + 18 > 100) ? true : ($r[$l + 18] != 0)))
		$m[4] = 0;
       
	$cm = null;
	$cm = array();
	foreach($m as $ia => $ib)
		if($ib == 1)
			$cm = array_merge($cm, array($ia));
       
	// Comprobamos que han salido movimientos
	if(($cm != null) ? count($cm) >= 1 : false)
		$fm = array_rand($cm); // Movimiento elegido
	else
		$can_move = false; // Aquí paramos
       
	if($can_move)
		foreach($cm as $ba => $bb)
			if($ba == $fm)
				$fm = $bb;
       
	// Nos movemos (si podemos)
	if($can_move)
		switch($fm)
		{
			case 1:
				$nl = ($l) + 3;
				$r[$nl] = $r[$l] + 1;
				$l = $nl;
				break;
			       
			case 2:
				$nl = ($l) + 22;
				$r[$nl] = $r[$l] + 1;
				$l = $nl;
				break;
			       
			case 3:
				$nl = ($l) + 30;
				$r[$nl] = $r[$l] + 1;
				$l = $nl;
				break;
			       
			case 4:
				$nl = ($l) + 18;
				$r[$nl] = $r[$l] + 1;
				$l = $nl;
				break;
			       
			case 5:
				$nl = ($l) - 3;
				$r[$nl] = $r[$l] + 1;
				$l = $nl;
				break;
			       
			case 6:
				$nl = ($l) - 22;
				$r[$nl] = $r[$l] + 1;
				$l = $nl;
				break;
			       
			case 7:
				$nl = ($l) - 30;
				$r[$nl] = $r[$l] + 1;
				$l = $nl;
				break;
			       
			case 8:
				$nl = ($l) - 18;
				$r[$nl] = $r[$l] + 1;
				$l = $nl;
				break;
 
			default:
				echo 'Error';
				$can_move = false;
				break;
		}
	}
 
	if($r[$l]  == 100)
	{
		$file_name = 'soluciones/last.txt';
		$file = fopen($file_name, 'r+');
		$last = fread($file, 11);
        ftruncate($file, 0);
        rewind($file);
		$last = $last + 1;
		fwrite($file, $last);
		fclose($file);
	       
		$content = '<!DOCTYPE html>
	<head>
		<title>Soluci&oacute;n ' . $last . ' del circuito Hamiltoniano - Ensaimada num&eacute;rica</title>
	</head>
	<body style="margin:3 0;">
			<table border="1" style="font-size: 57pt;text-align: center; border: 2px solid black;" cellpadding="2" cellspacing="0">';
		for($a = 1; $a <= 10; $a++)
		{
			$content .= "\n\t\t\t\t<tr>";
			for($b = 1; $b <= 10; $b++)
			{
				$content .= "\n\t\t\t\t\t<td width=\"90\" height=\"75\" style=\"height: 89px; text-align: center; border: 2px solid black;\" >";
				$content .= ($r[(($a-1)*10)+$b] == 0) ? "\n\t\t\t\t\t\t&nbsp;" : ("\n\t\t\t\t\t\t" . $r[(($a-1)*10)+$b]);
				$content .= "\n\t\t\t\t\t</td>";
			}
			$content .= "\n\t\t\t\t</tr>";
		}
		$content .= "\n\t\t\t</table></body></html>";
		echo 'Sol. $contenido encontrada y guardada. Intentos:',  $tries;
				$tries = 0;
		echo "\nBuscando soluciones...\n";
		$file = fopen('soluciones/' . $last . '.html', 'w');
		fwrite($file, $content);
		fclose($file);
	}
}

Cómo crear una Base de Datos de Hashes

¡Muy buenas amantes de la informática!
Bueno, la verdad es que ya hace siglos hice un generador de Hashes que generaba hashes en MD5 siguiendo un orden específico, el orden en cuestión era como el Excel (A, B… AZ, BA… ZZ, AAA..) pero incluyendo números y caracteres que se ponen comunmente en las contraseñas: ªº\|[email protected]»#~$%&/()=’?

Ese generador iba metiendo todas las contraseñas en una base de datos con su respectivo hash MD5, de forma que si buscaba el hash en cuestión en la base de datos me lo devolvía desencriptado (por decirlo de alguna forma, puesto que realmente no se puede hacer eso, pero si conseguir una coincidencia a fuerza bruta, que además son infinitamente múltiples en todos los casos posibles).

El código es sencillo y os lo dejo a todos para que lo aprovechéis. En un principio hice una versión para MySQL y luego una versión Flat File. Ambos son de uso recomendado en SSDs o dispositivos de almacenamiento flash por que en discos duros es muuuuy lento y tedioso.

Código Flat File (Pastebin para mejor formato)

$c = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ªº\\|[email protected]»#~$%&/()=\’?’;
$k = strlen($c);
function c($n)
{
global $k, $c;
$s = »;
$r = 1;
$b = $n;
while($b > pow($k, $r))
$b -= pow($k, $r++);
for($i = 0; $r > $i; $i++)
$s = substr($c, ($n/pow($k,$i)-1)%$k, 1) . $s;
return $s;
}

$x = scandir(‘C:\\txt’);
if($x[count($x)-1] == ‘..’)
$i = 0;
else
$i = count($x)-2;
echo number_format($i, 0, ‘.’, ‘.’);
while(true)
{
$i++;
$m = c($i);
$alg = hash_algos();
$sb = »;
$sa = »;
foreach(hash_algos() as $b => $al)
$sa .= hash($al, $m) . ((count(hash_algos()) > ($b + 1)) ? ‘ ‘ : »);
file_put_contents(‘C:\\txt\\’ . $i, $m . ‘ ‘ . $sa);
if($i%1000 == 0)
echo «\n» . number_format($i, 0, ‘.’, ‘.’);
}

Código para MySQL (Pastebin para mejor formato)

$x = mysqli_connect(‘127.0.0.1’, ‘root’, ‘contraseña’, ‘db’);
$c = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789ªº\\|[email protected]»#~$%&/()=\’?’;
$k = strlen($c);
function c($n)
{
global $k, $c;
$s = »;
$r = 1;
$b = $n;
while($b > pow($k, $r))
$b -= pow($k, $r++);
for($i = 0; $r > $i; $i++)
$s = substr($c, ($n/pow($k,$i)-1)%$k, 1) . $s;
return $s;
}
$q = mysqli_query($x, ‘SELECT id FROM hashes ORDER BY id DESC LIMIT 1’);
if(mysqli_num_rows($q) == 0)
$i = 0;
else
{
$p = mysqli_fetch_assoc($q);
$i = $p[‘id’];
}
echo number_format($i, 0, ‘.’, ‘.’);
while(true)
{
$i++;
$m = c($i);
$alg = hash_algos();
$sb = »;
$sa = »;
foreach(hash_algos() as $b => $al)
{
$sb .= ‘, `’ . $al . ‘`’;
$sa .= ‘\» . hash($al, $m) . ((count(hash_algos()) > ($b + 1)) ? ‘\’,’ : ‘\»);
}
mysqli_query($x, ‘INSERT INTO hashes (`value`’ . $sb . ‘) VALUES (\» . mysqli_real_escape_string($x, $m) . ‘\’, ‘ . $sa . ‘)’);
if($i%100 == 0)
echo «\n» . number_format($i, 0, ‘.’, ‘.’);
}

El SQL que debéis hacer para crear la tabla es tan fácil como ejecutar un script con un foreach en el cual por cada valor de hash_algos() (función que viene en PHP para obtener un array que nos indica todos los tipos de hashes disponibles) cree una fila varchar 255 y listo. En cualquier caso, aquí lo tenéis:

CREATE TABLE IF NOT EXISTS `hashes` (
`id` int(11) NOT NULL,
`value` varchar(255) NOT NULL,
`md2` varchar(255) NOT NULL,
`md4` varchar(255) NOT NULL,
`md5` varchar(255) NOT NULL,
`sha1` varchar(255) NOT NULL,
`sha224` varchar(255) NOT NULL,
`sha256` varchar(255) NOT NULL,
`sha384` varchar(255) NOT NULL,
`sha512` varchar(255) NOT NULL,
`ripemd128` varchar(255) NOT NULL,
`ripemd160` varchar(255) NOT NULL,
`ripemd256` varchar(255) NOT NULL,
`ripemd320` varchar(255) NOT NULL,
`whirlpool` varchar(255) NOT NULL,
`tiger128,3` varchar(255) NOT NULL,
`tiger160,3` varchar(255) NOT NULL,
`tiger192,3` varchar(255) NOT NULL,
`tiger128,4` varchar(255) NOT NULL,
`tiger160,4` varchar(255) NOT NULL,
`tiger192,4` varchar(255) NOT NULL,
`snefru` varchar(255) NOT NULL,
`snefru256` varchar(255) NOT NULL,
`gost` varchar(255) NOT NULL,
`gost-crypto` varchar(255) NOT NULL,
`adler32` varchar(255) NOT NULL,
`crc32` varchar(255) NOT NULL,
`crc32b` varchar(255) NOT NULL,
`fnv132` varchar(255) NOT NULL,
`fnv1a32` varchar(255) NOT NULL,
`fnv164` varchar(255) NOT NULL,
`fnv1a64` varchar(255) NOT NULL,
`joaat` varchar(255) NOT NULL,
`haval128,3` varchar(255) NOT NULL,
`haval160,3` varchar(255) NOT NULL,
`haval192,3` varchar(255) NOT NULL,
`haval224,3` varchar(255) NOT NULL,
`haval256,3` varchar(255) NOT NULL,
`haval128,4` varchar(255) NOT NULL,
`haval160,4` varchar(255) NOT NULL,
`haval192,4` varchar(255) NOT NULL,
`haval224,4` varchar(255) NOT NULL,
`haval256,4` varchar(255) NOT NULL,
`haval128,5` varchar(255) NOT NULL,
`haval160,5` varchar(255) NOT NULL,
`haval192,5` varchar(255) NOT NULL,
`haval224,5` varchar(255) NOT NULL,
`haval256,5` varchar(255) NOT NULL
) ENGINE=InnoDB AUTO_INCREMENT=486089 DEFAULT CHARSET=utf8;

ALTER TABLE `hashes`
ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `value` (`value`), ADD KEY `md2` (`md2`), ADD KEY `md4` (`md4`), ADD KEY `md5` (`md5`), ADD KEY `sha1` (`sha1`), ADD KEY `sha224` (`sha224`), ADD KEY `sha256` (`sha256`), ADD KEY `sha384` (`sha384`), ADD KEY `sha512` (`sha512`), ADD KEY `ripemd128` (`ripemd128`), ADD KEY `ripemd160` (`ripemd160`), ADD KEY `ripemd256` (`ripemd256`), ADD KEY `ripemd320` (`ripemd320`), ADD KEY `whirlpool` (`whirlpool`), ADD KEY `tiger128,3` (`tiger128,3`), ADD KEY `tiger160,3` (`tiger160,3`), ADD KEY `tiger192,3` (`tiger192,3`), ADD KEY `tiger128,4` (`tiger128,4`), ADD KEY `tiger160,4` (`tiger160,4`), ADD KEY `tiger192,4` (`tiger192,4`), ADD KEY `snefru` (`snefru`), ADD KEY `snefru256` (`snefru256`), ADD KEY `gost` (`gost`), ADD KEY `gost-crypto` (`gost-crypto`), ADD KEY `adler32` (`adler32`), ADD KEY `crc32` (`crc32`), ADD KEY `crc32b` (`crc32b`), ADD KEY `fnv132` (`fnv132`), ADD KEY `fnv1a32` (`fnv1a32`), ADD KEY `fnv164` (`fnv164`), ADD KEY `fnv1a64` (`fnv1a64`), ADD KEY `joaat` (`joaat`), ADD KEY `haval128,3` (`haval128,3`), ADD KEY `haval160,3` (`haval160,3`), ADD KEY `haval192,3` (`haval192,3`), ADD KEY `haval224,3` (`haval224,3`), ADD KEY `haval256,3` (`haval256,3`), ADD KEY `haval128,4` (`haval128,4`), ADD KEY `haval160,4` (`haval160,4`), ADD KEY `haval192,4` (`haval192,4`), ADD KEY `haval224,4` (`haval224,4`), ADD KEY `haval256,4` (`haval256,4`), ADD KEY `haval128,5` (`haval128,5`), ADD KEY `haval160,5` (`haval160,5`), ADD KEY `haval192,5` (`haval192,5`), ADD KEY `haval224,5` (`haval224,5`), ADD KEY `haval256,5` (`haval256,5`);

Espero que os sirva de ayuda para vuestros proyectos,
Saludos :B


Páginas:12