Skip to content

Instantly share code, notes, and snippets.

@RascalTwo
Last active August 5, 2021 05:02
Show Gist options
  • Save RascalTwo/69717a04a9a14dca1b1bd8148916d921 to your computer and use it in GitHub Desktop.
Save RascalTwo/69717a04a9a14dca1b1bd8148916d921 to your computer and use it in GitHub Desktop.
JS Custom Hashing function with benchmarks

JavaScript Custom Hashing Function

A custom string hashing function written in JavaScript.

Benchmarks

Version Words Runtime (Seconds) Collisions %
1 7,849,570 6.169 1,380 0.019460504060899532
2 7,849,570 6.853 98 0.0012484760311711341

Explanation

I continued trying variations of the available operators in JS until I got the value as low as possible while not sacrificing too much runtime.

// This is a basic collision tester that can make checking for collisions a little easier! To use it, enter each key (in this case, a word) you want to check into the test-words.txt file, with each key in a different line. Then, run collision-tester.js, and the program will tell you how many collisions it detected between the word you've inserted.
var oldlog = console.log
console.log = function() {}
const fs = require('fs');
const usr = require("./index.js");
console.log = oldlog
function areSetsEqual(a, b) {
if (a.size !== b.size) return false;
for (const c of a) if (!b.has(c)) return false;
return true;
}
function testCollisions(filepath){
fs.readFile(filepath, 'utf8' , (err, data) => {
if (err) return console.error(err);
const words = data.split('\n');
const start = Date.now();
const hashes = new Set(words.map(usr.my_hash));
const end = Date.now();
const collisions = words.length - hashes.size;
console.log("\t" + filepath + " results")
console.log("Total words: " + words.length);
console.log("Number of Collisions Detected: " + collisions);
console.log("Collision %: " + collisions / words.length * 100)
console.log("Runtime: " + (end - start))
if (!areSetsEqual(hashes, new Set(words.map(usr.my_hash)))) {
console.error('Hash function is NOT stable!')
}
});
}
testCollisions('test-words.txt');
testCollisions('generated-words.txt');
const fs = require('fs');
const DURATION = 10;
const values = new Set();
const started = Date.now();
let characters = 1;
for(let remaining; remaining = DURATION * 1000 - (Date.now() - started), remaining > 0; characters++){
for (let _ = 0; _ < 100; _++){
values.add(Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, characters))
}
process.stdout.write((remaining / 1000).toFixed(1) + ' \r');
}
console.log(`Generated ${characters * 100} strings!`);
console.log('Writing to file...')
fs.writeFileSync('./generated-words.txt', Array.from(values).sort().join('\n'));
// This function, my_hash(), is where you should write your hash function. Like last module, input is a string, and the hash function should return an integer.
/**
* @param {string} input
* @returns {string}
*/
function my_hash(input){
let hash = input.length;
for (let i = 0; i < input.length; i++){
hash += (hash ^ input.charCodeAt(i)) * (hash << 6)
}
return hash * input.length;
}
// An example test case!
console.log(my_hash("boblover1234"));
// This is for the collision tester, and can be ignored (it passes your function onto the collision tester to test)
module.exports = {my_hash};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment