Bizzy817
Bizzy817

Reputation: 65

How to create a letter scoring function that scores vowels differently from consonants

So I'm trying to create a word scoring algorithm that gives one point for every consonant and 3 point for every vowel. But every attempt I've tried has failed which means something isn't mentally clicking for me and I need help understanding what I'm doing wrong

I've searched all over the web and found numerous ways to check letters of a word and count vowels, which I've tried customizing and using for my scoring algorithm and I still keep getting the wrong scoring output when testing each approach. I've looked at using iterative approached and using regular expressions. Someone was telling me that my fault is in my second loop but I'm not sure how to correct it.

//The attempt where apparently the second loop is the problem: 
vowelBonus= (word)=>{
  let score = 0;
  const vowels = ["a","e","i","o","u"];
  word = word.toLowerCase();
  for (letter in word){
    vowels.forEach((value)=>{
      if (letter === value){
        score += 3
      }else if(letter !== value){
        score += 1
      }
    })
    return score
  }
}

// An attempt using a regular expression which I kind of prefer after reading up on them

vowelBonus = (word)=>{
  let vowel = word.match(/[aeiou]/gi);
  let vCount = 0
  let consCount = 0
  let score = vCount + consCount
  if(vowel.length){
    vCount += 3
  }else if (!vowel.length){
    consCount =+ 1
  }
  return score
}

//I have about 3-5 other versions I've toyed around with but I'd like to stay in the ballpark of something like the two snippets I've pasted above. 

//One version keeps giving an output of 0. Another gives increments of 5, and I've had a few give a result of 1-5. I'm expecting the result to be 1pt for every consonant and 3pts for every vowel. Meaning if I type in the word "code", the result should be 8pts.

Upvotes: 3

Views: 750

Answers (3)

Matt Oestreich
Matt Oestreich

Reputation: 8528

EDIT: Don't forget about edge cases, like if someone supplies a space in the word... Just something to consider...

EDIT 2: Added example using regex that ignores spaces if they are supplied..

Something like this should work.. I find it easiest to use the Array.includes method for things like this.

Let me know if you have any questions!

function scoreWord(word) {
  // Ignores spaces
  return word.replace(/\s/g,'').toLowerCase().split("").reduce((a, i) => 
    a += ["a", "e", "i", "o", "u"].includes(i) ? 3 : 1, 0);
}


function scoreWordSimplified(word) {
  // Ignores spaces; Simplified example
  let wordArray = word.replace(/\s/g, "").toLowerCase().split("");
  let vowels = ["a", "e", "i", "o", "u"];
  let pointsForVowel = 3;
  let pointsForConsonant = 1;
  let finalScore = 0;

  wordArray.forEach(letter => {
    if (vowels.includes(letter)) {
      finalScore += pointsForVowel;
    } else {
      finalScore += pointsForConsonant;
    }
    /** Or you could do:
     * finalScore += vowels.includes(letter) ? pointsForVowel : pointsForConsonant;
     */
  });

  return finalScore;
}


let vowelBonus = (word)=>{
  // credit: @Code Maniac
  // Ignores spaces
  let _word = word.replace(/\s/g,'');
  let vowel = _word.match(/[aeiou]/gi);
  let wordLength = _word.length;
  let vowelLength = vowel && vowel.length;
  return vowel ? (wordLength - vowelLength) + vowelLength *3 : wordLength
}

let score1 = scoreWord("some word");
let score2 = vowelBonus("some word");
let score3 = scoreWordSimplified("some word");

console.log("scoreWord: ", score1);
console.log("vowelBonus: ", score2);
console.log("scoreWordSimplified: ", score3);

Upvotes: 1

Code Maniac
Code Maniac

Reputation: 37755

Well there are lots of problems to notice in you code.

In example 1

  • Do not use for .. in for looping over the strings,
  • when you iterate over string using for ... in it returns the index ( key ) of string not the value.
  • You're returning value inside for...in after first iteration itself, whereas you need to return value after loop,
  • Inside the loop you're looping over the vowels everytime and if the value is found you're adding 3 if not found you're adding 1, but for each single characters you're looping on vowels which adds extra count than it should

In example 2

  • You're matching with regex and than if the length is greater than zero you're adding value just once whereas it should be match.length * 3 and for the remaining length it should be (word.length - match.length)

so you can simply do this

let vowelBonus = (word)=>{
  let vowel = word.match(/[aeiou]/gi);
  let wordLength = word.length
  let vowelLength = vowel && vowel.length
  return vowel ? (wordLength - vowelLength) + vowelLength *3 : wordLength
}

console.log(vowelBonus("aeiou"))
console.log(vowelBonus("abcd"))
console.log(vowelBonus("aeibcd"))

Upvotes: 1

Diego Shevek
Diego Shevek

Reputation: 495

It's simpler with regex:

(word)=>{
  let vowel = word.match(/[aeiou]/gi);
  vowelScore = 3 * vowel.length
  consScore = word.length - vowel.length
  return vowelScore + consScore
}

Upvotes: 1

Related Questions