Skip to content

Instantly share code, notes, and snippets.

@lukemorales
Last active April 9, 2022 00:00
Show Gist options
  • Save lukemorales/f6578f60c366f771d28b063e8fbb1c38 to your computer and use it in GitHub Desktop.
Save lukemorales/f6578f60c366f771d28b063e8fbb1c38 to your computer and use it in GitHub Desktop.
Attempt of creating a password generator for Advent of Javascript
const createArrayOfChars = (length: number, initial: number) => {
return Array.from({ length }, (_, index) => String.fromCharCode(index + initial));
}
const numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
const symbols = [ ...createArrayOfChars(14, 33), ...createArrayOfChars(6, 58), ...createArrayOfChars(4, 123)];
const lowerCaseLetters = createArrayOfChars(26, 97);
const upperCaseLetters = lowerCaseLetters.map((letter) => letter.toUpperCase());
type CharType = 'numbers' | 'symbols' | 'upperCase' | 'lowerCase';
type Options = Record<`has${Capitalize<CharType>}`, boolean>;
const generatePassword = (length: number, options: Partial<Options> = {}) => {
const availableCharGroups = [
(options.hasNumbers && numbers),
(options.hasSymbols && symbols),
(options.hasLowerCase && lowerCaseLetters),
(options.hasUpperCase && upperCaseLetters),
].filter(Boolean);
let password = ''
if (availableCharGroups.length === 0) {
return password
}
const groupsCountLookup = availableCharGroups.reduce((lookup, _, index) => {
lookup[index] = 0;
return lookup
}, {} as Record<number, number>)
while (length--) {
const unmatchedGroups = Object.keys(groupsCountLookup).filter(key => groupsCountLookup[key] === 0).map(Number);
let randomGroupIndex = Math.floor(Math.random() * availableCharGroups.length);
if (unmatchedGroups.length > 0 && !unmatchedGroups.includes(randomGroupIndex)) {
const randomUnmatchedIndex = Math.floor(Math.random() * unmatchedGroups.length);
randomGroupIndex = unmatchedGroups[randomUnmatchedIndex];
}
groupsCountLookup[randomGroupIndex]++;
const charGroup = availableCharGroups[randomGroupIndex];
const randomCharIndex = Math.floor(Math.random() * charGroup.length);
let randomChar = charGroup[randomCharIndex];
if (password[password.length - 1] === randomChar) {
randomChar = charGroup[randomCharIndex + 1] || charGroup[randomCharIndex - 1];
}
password = [...(password + randomChar)].sort(() => Math.random() - 0.5).join('');
}
return password;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment