pigeoned
pigeoned

Reputation: 15

How to filter vowel and consonant letters generated from a random string

I am making a word game that picks 8 random letters from the alphabet and the player must find words that use these letters. I must find out a way to make the letters picked always contain 3 vowels and 5 consonants. I would appreciate your help

Here is the code I am using to pick the random letters for the game

function makeid(length) {
  var result           = '';
  var characters       = 'aaabcdeeefghiiijklmnooopqrstuuuvwxyz';
  var charactersLength = characters.length;
  for (var i = 0; i < length; i++) {
    let letter = characters.charAt(Math.floor(Math.random() * charactersLength));
    while (result.match(letter)) {
      letter = characters.charAt(Math.floor(Math.random() * charactersLength));
    }
    result += letter;
  }
  return result;
}

console.log("Id of 8 characters", makeid(8))

Upvotes: 1

Views: 1513

Answers (2)

Ruan Mendes
Ruan Mendes

Reputation: 92334

@Lars answer is almost perfect, the only problem is that the final string is not truly shuffled.

I suggest you just create two arrays: random vowels and random consonants and then just shuffle them using Fisher-Yates' algorithm.

function getRandomCharsFromString(str, length) {
    return Array.from({length}, () => {
      return str[Math.floor(Math.random() *  str.length)]
    });
}

function shuffle(str) {
  var a = str.split(""),
    n = a.length;

  for (var i = n - 1; i > 0; i--) {
    var j = Math.floor(Math.random() * (i + 1));
    // Swap them with ES6 destructuring magic
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a.join("");
}

function getRandomString() {
  const vowels = 'aeiou';
  const consonants = 'bcdfghjklmnpqrstvwxyz';

  const randomVowels = getRandomCharsFromString(vowels, 3);
  const randomConsonants = getRandomCharsFromString(consonants, 5);
  
  const randomWord = [...randomVowels, ...randomConsonants].join('')
  return shuffle(randomWord)
}


console.log('random string:', getRandomString())

No repeated letters

You mentioned you don't want repeated letters; many words in English have duplicate letters. Why is that a requirement?

You can shuffle the vowels and consonants and get the first x characters from that string.

// This version makes sure characters are not repeated
function getRandomCharsFromString(str, length) {
    return shuffle(str).slice(0, length);
}

function shuffle(str) {
  var a = str.split(''),
    n = a.length;

  for (var i = n - 1; i > 0; i--) {
    var j = Math.floor(Math.random() * (i + 1));
    // Swap them with ES6 destructuring magic
    [a[i], a[j]] = [a[j], a[i]];
  }
  return a;
}

function getRandomString() {
  const vowels = 'aeiou';
  const consonants = 'bcdfghjklmnpqrstvwxyz';

  const randomVowels = getRandomCharsFromString(vowels, 3);
  const randomConsonants = getRandomCharsFromString(consonants, 5);
  
  const randomWord = [...randomVowels, ...randomConsonants].join('')
  return shuffle(randomWord).join('')
}


console.log('random string:', getRandomString())

Upvotes: 1

zer00ne
zer00ne

Reputation: 44108

  1. Have one array of consonants and one array for vowels.

  2. Use a shuffling function, here's a terse one liner:

    const shuffle = array => array.sort(() => Math.random() - 0.5);
    
  3. The function above will return a given array in a random order, so you'll need to shorten each array by 5 (consonants) and 3 (vowels):

    let C = shuffle(consonants);
    let V = shuffle(vowels); 
    
    C.length = 5;
    V.length = 3;
    

    Easy 😎

// Utility Function (optional)
const log = data => console.log(JSON.stringify(data));

const consonants = ["B", "C", "D", "F", "G", "H", "J", "K", "L", "M", "N", "P", "Q", "R", "S", "T", "V", "W", "X", "Y", "Z"];
const vowels = ["A", "E", "I", "O", "U"];

const shuffle = array => array.sort(() => Math.random() - 0.5);

let C = shuffle(consonants);
let V = shuffle(vowels); 

C.length = 5;
V.length = 3;

const result = shuffle(V.concat(C));

log(result);

Upvotes: 1

Related Questions