0

I am trying to solve the problem if the array of strings is pangram, which contains letters a-z. If a string is pangram, return 1, if a string is not pangram, return 0. The following code checking an individual letter in the string, but I encountered the problem to check each string. For example, the "The quick brown fox jumps over the lazy dog" is pangram, give 1, and "This is not a pangram" give 0, after the for loop finished the iteration of two strings, the result should be returned 10

function isPangram(string) {
  let result = []
  const letters = "abcdefghijklmnopqrstuvwxyz".split("")
  for (let i = 0; i < string.length; i++) {
    for (let j = 0; j < letters.length; j++) {
      if (string[i].includes(letters[i])) {
        result.push(1)
      }
      if (!string[i].includes(letters[i])) {
        result.push(0)
      }
    }
  }
  return result.join("")
}

console.log(isPangram(["The quick brown fox jumps over the lazy dog", "This is not a pangram"]))
Ckate
  • 47
  • 6
  • Do you mean that 10 is the expected result or the actual result? (Please provide both, by the way.) – Brian McCutchon Mar 15 '21 at 20:44
  • 1
    Please write the result you expect – Bahador Raghibizadeh Mar 15 '21 at 20:50
  • @BahadorRaghibizadeh 10 is the expected result. The string parameter has two strings. I am trying to check each strings in the array if it is pangram. If yes, that string will give 1, and if no, then give 0. After the loop finished the iteration, the result variable return should be 10 – Ckate Mar 15 '21 at 21:12
  • @BrianMcCutchon 10 is the expected result. The string parameter has two strings. I am trying to check each strings in the array if it is pangram. If yes, that string will give 1, and if no, then give 0. After the loop finished the iteration, the result variable return should be 10 – Ckate Mar 15 '21 at 21:12
  • Ok @Ckate, I'd expected you wanted an array with your numeric results. Now that you've clarified, I have updated my [answer](https://stackoverflow.com/a/66645465/14749002) to produce the desired output – BiOS Mar 15 '21 at 21:20
  • You are adding `1` or `0` for every letter. You should wait until the loop is finished before pushing a value into the array. Before the loop starts, create a variable set to `1`. This assumes the string is a pangram. Then go through each letter of the alphabet. If it is not in the string, set the variable to `0` and `break`. No need to check anymore letters. Add the variable to the results list. – 001 Mar 15 '21 at 21:24
  • Also, convert the string to lower case since your letters are all lower case. – 001 Mar 15 '21 at 21:26
  • @JohnnyMopp Thank you so much! I stuck there trying to find a way to not trying to add 1 or 0 for every letter. – Ckate Mar 15 '21 at 21:44
  • Just do: ((string) => string.length === string.match(/([a-z\s])\w+/gi)[0].length)("Hello World."); – Jens Ingels Mar 15 '21 at 22:20

3 Answers3

1

If what you are looking to is having the function to work on an array of strings, then you could give an array as argument to the function, like you are doing right now, and then perform an iteration on the given argument, to check if the string is pangram, and if that is the case, append 1 to a string, which is eventually returned.

I also suggest to use regex to check if your string is pangram (credits to this answer).

function isPangram(strArray){ 
    var resultStr = "";
    let reg = /(?=.*a)(?=.*b)(?=.*c)(?=.*d)(?=.*e)(?=.*f)(?=.*g)(?=.*h)(?=.*i)(?=.*j)(?=.*k)(?=.*l)(?=.*m)(?=.*n)(?=.*o)(?=.*p)(?=.*q)(?=.*r)(?=.*s)(?=.*t)(?=.*u)(?=.*v)(?=.*w)(?=.*x)(?=.*y)(?=.*z)./i 
    strArray.forEach(function(e) {
        //The value of res is determined by the outcome of the regex check, through a ternary operator
        let res = (reg.test(e)) ? "1" : "0";
        resultStr += res;
    })

    return parseInt(resultStr);
}

console.log(isPangram(["The quick brown fox jumps over the lazy dog","This is not a pangram"]))

You may unwrap the resultStr from the parseInt() function if you'd rather have your result as string.

Or if you would like to keep your current loop structure, you could and all the results together, and add the finally obtained one to a string:

function isPangram(strArray) {

var resStr = "";
const letters = "abcdefghijklmnopqrstuvwxyz".split("");

for (let i in strArray) {
    var tempRes = true;
    for (j in letters) {
        tempRes = tempRes & (strArray[i].toLowerCase().includes(letters[i]))
    }
    resStr += tempRes;
}

return resStr
}

console.log(isPangram(["THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG", "This is not a pangram"]))

As also pointed out by @Johnny Mop, if you instead used the condition (strArray[i].includes(letters[i])) to determine the first time a 0 is obtained, you could break the loop to save some time (not really much though, in this case). And as well he's right to point out that you'll need toLowerCase(), otherwise THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG won't result as pangram.

BiOS
  • 2,282
  • 3
  • 10
  • 24
  • Thank you! I am comfortable using the for loop, but it is great to see using the regex to solve the problem!!!! – Ckate Mar 15 '21 at 21:38
  • I am glad I could help! I honestly like the regex approach because of its clean look, but just in case I have edited my answer to add some references to the loop approach that you are using, too! PS I am just seeing that you have not [accepted](https://stackoverflow.com/help/someone-answers) an answer before, so if you didn't know about this function, you could consider accepting my answer if you found that was the right solution to your problem. Have a nice day! – BiOS Mar 15 '21 at 22:13
0

An algorithmic solution using ES6 maps:

const isPangram = (sentences) => {
  let results = '';
  sentences.forEach((sentence) => {
    const characterMap = createCharacterMap();
    for (let index = 0; index < sentence.length; index++) {
       const currentChar = sentence[index].toLowerCase();
       const existingKeyValue = characterMap.get(currentChar)
       if(existingKeyValue === 0) {
         characterMap.set(currentChar, 1)
       }
    }
    let hasAll = true;
    [...characterMap.values()].forEach((char) => {
      if(char !== 1) {
        hasAll = false;
      }
    })
    results = results + (hasAll ? 1 : 0)
  })
  return results;
}

const createCharacterMap = () => {
  const chMap = new Map();
  for(i = 97; i < 123; i++) {
    chMap.set(String.fromCharCode(i), 0)
  }
  return chMap;
}

console.log(isPangram([
  "The quick brown fox jumps over the lazy dog", 
                       "This is not a pangram"
                      ]))
Rohit Kashyap
  • 1,553
  • 1
  • 10
  • 16
0

I did something similar when working with countries/states/ or something, but you can also loop through the string and store each letter into an object.

Then once the loop is done, check if it has 26 keys and return 1 or 0

function isPangram(strArray){

    let resultsArr = strArray.map(function(str) {
    
      // Object to store letters already seen
      let letters = {},
        // format string into an array that is all lowercase
        // no whitespace
        splitStr = str.toLowerCase().replaceAll(/\s/g, '').split('');
        
        for (let i = 0; i < splitStr.length; i++) {
          let char = splitStr[i];
          // If character hasn't been seen before, add it
          if (char in letters === false) {
            letters[char] = 1;
            continue;
          }
          // otherwise, just increment
          letters[char] += 1;
        }
      
      // if it is an alphabet long, return 1, else 0
      return Object.keys(letters).length === 26 ? 1 : 0;
    });
    
    // join as a string
    return resultsArr.join('');
}

console.log(isPangram(["The quick brown fox jumps over the lazy dog","This is not a pangram"]))
frankie
  • 201
  • 1
  • 6