Skip to content

Instantly share code, notes, and snippets.

@steve-taylor
Created November 4, 2018 11:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save steve-taylor/c9ea9c5deb16b2e663991e06416efb9b to your computer and use it in GitHub Desktop.
Save steve-taylor/c9ea9c5deb16b2e663991e06416efb9b to your computer and use it in GitHub Desktop.
Given a list of words, generate a list of random words that start with the same letter as the original words.
#!/usr/bin/env node
const fs = require('fs');
const util = require('util');
const readline = require('readline');
const crypto = require('crypto');
const readFile = util.promisify(fs.readFile);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
async function question(prompt) {
return new Promise((resolve) => {
rl.question(prompt, resolve);
});
}
async function main() {
const maxWordLength = parseInt(await question('Max word length [unlimited] '), 10) || 1000;
const numResults = parseInt(await question('Number of results [20]'), 10) || 20;
// Read dictionary and index by first letter
const data = await readFile('/usr/share/dict/words', 'utf8');
const wordsByFirstLetter = data.split('\n').reduce((wordsByFirstLetter, word) => {
const normalizedWord = word.trim().toLowerCase();
if (normalizedWord && normalizedWord.length <= maxWordLength) {
const firstLetter = normalizedWord[0];
let words = wordsByFirstLetter[firstLetter];
if (!words) {
words = [];
wordsByFirstLetter[firstLetter] = words;
}
words.push(normalizedWord);
}
return wordsByFirstLetter;
}, {});
// For each input word, generate a random word starting with the same letter that doesn't match it.
const answer = await question('Enter some words to create a mnemonic > ');
const words = answer.trim().toLowerCase().split(' ');
for (let i = 0; i < numResults; ++i) {
const mnemonic = words.map((word) => {
const firstLetter = word[0];
const candidateWords = wordsByFirstLetter[firstLetter];
const maxRandomNumber = (2 ** 24) - 1;
let randomWord = word;
while (randomWord === word) {
const randomNumber = parseInt(crypto.randomBytes(3).toString('hex'), 16);
const randomIndex = Math.floor(randomNumber / maxRandomNumber * candidateWords.length);
randomWord = candidateWords[randomIndex];
}
return randomWord;
}).join(' ');
console.log(mnemonic);
}
}
main().then(() => void process.exit(0));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment