Skip to content

Instantly share code, notes, and snippets.

@azanli
Last active July 27, 2021 18:22
Show Gist options
  • Select an option

  • Save azanli/d76796a79b39d446f4a90c1610709751 to your computer and use it in GitHub Desktop.

Select an option

Save azanli/d76796a79b39d446f4a90c1610709751 to your computer and use it in GitHub Desktop.
Scramble an ordered list of digits hashed by a secret passphrase
/*
* Scramble Ordered Digits
*
* This function takes in a `passphrase` and `limit` argument and returns
* a scrambled list of digits, n ... {limit}.
*
* This assumes that the original ordered digits are whole numbers starting
* from 1 ... {limit} where `limit` is the max digit.
*
* For example, `scrambleOrderedDigits('Hello World')` hashes 24 digits to the order on the right-hand side:
*
* 1 13 >> 9 13
* 2 14 >> 24 2
* 3 15 >> 6 14
* 4 16 >> 18 3
* 5 17 >> 1 15
* 6 18 >> 22 4
* 7 19 >> 5 16
* 8 20 >> 17 11
* 9 21 >> 8 12
* 10 22 >> 20 21
* 11 23 >> 10 7
* 12 24 >> 23 19
*/
const scrambleOrderedDigits = (passphrase, limit = 24) => {
if (typeof passphrase !== 'string') {
throw new Error('Passphrase must be a string.');
} else if (passphrase.length < 4) {
throw new Error('Passphrase must contain a minimum of four units.');
}
let key = passphrase + passphrase.split('').reverse().join('');
const map = {};
const result = [];
const scrambledResult = [];
const hashes = key.split('').map((char, idx) => {
let code = char.charCodeAt();
if (map[code]) {
while (map[code]) {
code += key.length;
}
}
map[code] = true;
return code;
});
let seq = 0;
let nxt = 0;
while (scrambledResult.length < limit) {
let hash = Math.floor(hashes[seq] / 2) ** Math.floor(hashes[nxt] / 2);
while (map[hash] && isNaN(hash)) {
hash = Math.floor(hashes[seq] / 2) ** Math.floor(hashes[nxt++] / 2);
}
if (!isNaN(hash) && scrambledResult.indexOf(hash) === -1) {
map[hash] = true;
scrambledResult.push(hash);
}
if (seq + nxt > hashes.length - 2) {
seq += 1;
nxt = seq;
} else {
nxt += 1;
}
}
const sortedResult = [...scrambledResult].sort((a, b) => a - b);
for (let i = 0; i < limit; i += 1) {
result.push(scrambledResult.indexOf(sortedResult[i]) + 1);
}
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment