Hashing una cadenaQuiero una función hash en JMP para cadenas cortas. (Lo necesito para crear claves de base de datos enteras anónimas a partir de los datos de la fila).
No necesita ser de calidad criptográfica, solo debe tener un resultado de 64 bits (o de 128 bits) y tener una tasa de colisión razonablemente baja. Intenté usar Blob MD5 () (con truncamiento a 64 bits), pero no puedo creer lo lento que es. (¡Pruébalo en una mesa con 500,000 filas!). ¿Alguien ha creado o vinculado a un algoritmo hash rápido en JSL? ¿Qué hay de sembrar el generador de números aleatorios de JSL con alguna función de la cadena de entrada? No necesito la calidad NIST, pero sí necesito algo rápido y no demasiado sucio que dé el mismo resultado en todas las plataformas.
¿Se puede llamar desde JSL a uno de los muchos algoritmos hash de C ++ o Java que existen? ¿Cómo?
PS Tal vez JMP 14.1 podría incluir algunas funciones hash mejores en su biblioteca estándar. ¿Qué hay de incluir SHA?
Re: Hashing una cadenaCraige,
Tal vez estaba siendo demasiado duro con Blob MD5. Es más lento que eso en mi máquina con mis cadenas de entrada. Sin embargo, gracias por la comprobación objetiva.
Juan
Re: Hashing una cadenaEsto se ejecuta en unos 10 segundos en 1.000.000 filas.
start = Tick Seconds();
dt = New Table( "Untitled",
Add Rows( 1e6 ),
New Column( "Column 1", Numeric, "Continuous", Format( "Best", 12 ), Formula( Row() ) ),
New Column( "Column 2", Character, "Nominal", Formula( Hex( Blob MD5( Char To Blob( Char( :Column 1 ) ) ) ) ) )
);
dt << runformulas; // run the formulas now, not in the background
stop = Tick Seconds();
Show( stop - start );
Using MD5 for hashUsando MD5 para el hash
Re: Hashing una cadenaGracias por esta solución!
Desafortunadamente, estoy en Mac, así que no puedo usar vbs. Pero ahora veo en tu ejemplo cómo usar RunProgram, y voy a intentar que funcione para CityHash ( https://opensource.googleblog.com/2011/04/introducing-cityhash.html ).
Re: Hashing una cadenaJohn Madden,
No soy un experto y esto podría no satisfacer sus necesidades. A continuación se muestra un VBscript para el cifrado SHA256 y MD5. Encuéntralo aquí en este enlace.
https://gist.github.com/jermity/557de47a978f7a7c4a74
Sólo sé Windows. Copie el archivo adjunto y cambie la extensión a .vbs. Abra una ventana de Comando, cd al directorio de guardado y escriba jerhash.vbs para obtener la sintaxis de uso. El script incrustado convierte los nombres de los estados. Este script vbs no parece permitir una lista de valores. Los 52 nombres de estados tomaron 8.2 segundos, y estoy seguro de que la sobrecarga para la conexión del programa de ejecución se suma a eso. La secuencia de comandos adjunta muestra un método alternativo para crear un archivo .bat. tomó un promedio de 0.1 segundos para los 52 ítems. No leí en el archivo. Ese es otro enfoque. Genera los 500k offline y luego lee en el archivo.
Eso es todo lo que tengo. Saludos.

mytbl = New Table("testit", New Column("States", Character,
Values({"Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut",
"District of Columbia", "Delaware", "Florida", "Georgia", "Hawaii", "Idaho",
"Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", "Maine",
"Maryland", "Massachusetts", "Michigan", "Minnesota", "Mississippi", "Missouri",
"Montana", "Nebraska", "Nevada", "New Hampshire", "New Jersey", "New Mexico",
"New York", "North Carolina", "North Dakota", "Ohio", "Oklahoma", "Oregon",
"Pennsylvania", "Rhode Island", "South Carolina", "South Dakota", "Tennessee",
"Texas", "Utah", "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin",
"Wyoming"}) ), NewColumn("Code",Character)
);
t1 = tick seconds();
for(i=1, i<=nrow(mytbl), i++,
:Code[i] = Trim(RunProgram(Executable("cscript"),
Options(EvalInsert("\[//nologo c:\temp\jerhash.vbs /A:sha256 /S:"^:States[i]^"]\") ),
ReadFunction("text")
));
);
t2= tickseconds();
show(t2-t1);
Re: Hashing una cadenaPor cierto, aquí está la solución que finalmente decidí:
// ==========================
// ::String Hash()
// ==========================
myStringHash = New Custom Function(
"Global",
"String Hash",
Function( {str, length = 64},
{bytes},
bytes = Match( length, 64, 8, 32, 4, Throw( "Bad argument in ::String Hash; hash length must be 64 (default) or 32." ) );
Subscript( Blob To Matrix( Blob Peek( Blob MD5( Char To Blob( str, "utf-8" ) ), 0, bytes ), "int", bytes, "little" ), 1 );
)
);
myStringHash << Description(
"Accepts a string as input, and returns an unsigned 64-bit or 32-bit integer hash of the string, generated by truncation of the (128-bit) MD5 hash of the input string.
The first parameter is the input string to be hashed.
The second, optional parameter is either the number 64 or the number 32. This selects whether the result will be a 64-bit (8-byte) integer, or a 32-bit (4-byte) integer. If not specified, the function defaults to 64-bit (8-byte). If a value other than 64 or 32 is entered, an error results."
);
myStringHash << Prototype( "::String Hash (string, <64|32>)" );
myStringHash << Example( "z = ::String Hash ( \!"This is a string\!" ); Show ( Format( z, 20, 0) )" );
myStringHash << Parameter( "String", "Input string" );
myStringHash << Parameter( "Number", "<64 or 32 (default is 64)>" );
myStringHash << Formula Category( "Database" );
Add Custom Functions( {myStringHash} );