Introduction
You work for a company that sells fonts through their website.
They’d like to show a different sentence each time someone views a font on their website.
To give a comprehensive sense of the font, the random sentences should use all the letters in the English alphabet.
They’re running a competition to get suggestions for sentences that they can use.
You’re in charge of checking the submissions to see if they are valid.
Pangram comes from Greek, παν γράμμα, pan gramma, which means "every letter".
The best known English pangram is:
> The quick brown fox jumps over the lazy dog.
Instructions
Instructions
Your task is to figure out if a sentence is a pangram.
A pangram is a sentence using every letter of the alphabet at least once.
It is case insensitive, so it doesn’t matter if a letter is lower-case (e.g. k) or upper-case (e.g. K).
For this exercise, a sentence is a pangram if it contains each of the 26 letters in the English alphabet.
Dig Deeper
every with includes
every with includes on lowercased letters
export function isPangram(input) {
const inputLowered = input.toLowerCase();
return [...'abcdefghijklmnopqrstuvwxyz'].every((c) =>
inputLowered.includes(c),
);
}
- This begins by lowercasing the input by using the
String toLowerCase method.
- It uses spread syntax to make an Array out of a
string of the alphabet.
- It then checks if all letters in the alphabet are contained in the input,
using the
Array method every with the String method includes.
If all letters of the alphabet are in the input, then the function returns true.
Set with size
Set with size
export function isPangram(input) {
return new Set(input.toLowerCase().match(/[a-z]/g)).size === 26;
}
This approach creates a Set of the unique letters in the input and tests its size to determine the result.
- It first creates a new
Set made from the lowercased characters of the input
that only match the regular expression pattern for letters from a-z.
- The function returns if the
size of the Set is 26.
If the number of unique letters in the Set is equal to the 26 letters in the alphabet, then the function will return true.
Shortening
When the body of a function is a single expression, the function can be implemented as an arrow function, like so
export const isPangram = (input) =>
new Set(input.toLowerCase().match(/[a-z]/g)).size === 26;
Notice that return and the curly braces are not needed.
Bit field
Bit field
const A_LCASE = 97;
const A_UCASE = 65;
const ALL_26_BITS_SET = 67108863;
export function isPangram(input) {
let phrasemask = 0;
[...input].forEach((letter) => {
if (letter >= 'a' && letter <= 'z')
phrasemask |= 1 << (letter.charCodeAt(0) - A_LCASE);
else if (letter >= 'A' && letter <= 'Z')
phrasemask |= 1 << (letter.charCodeAt(0) - A_UCASE);
});
return phrasemask == ALL_26_BITS_SET;
}
This solution uses the ASCII value of the letter to set the corresponding bit position.
Some constants are defined for readability in the function.
The ASCII value for a is 97.
The ASCII value for A is 65.
The value for all of the rightmost 26 bits being set is 67108863.
- Spread syntax is used to make an
Array of the characters in the input.
- The
Array method forEach loops through the characters and looks for a character being a through z or A through Z.
- If a letter is found, then its ASCII value is taken by the
charCodeAt method.
`charCodeAt` actually returns the UTF-16 code unit for the character, which is an integer between `0` and `65535`.
For the letters `a`-`z` and `A`-`Z`, the UTF-16 number is the same value as the ASCII value.
- If the lowercase letter is subtracted by
97, then a will result in 0, because 97 minus 97 equals 0.
z would result in 25, because 122 minus 97 equals 25.
So a would have 1 shifted left 0 places (so not shifted at all) and z would have 1 shifted left 25 places.
- If the uppercase letter is subtracted by
A, then A will result in 0, because 65 minus 65 equals 0.
Z would result in 25, because 90 minus 65 equals 25.
So A would have 1 shifted left 0 places (so not shifted at all) and Z would have 1 shifted left 25 places.
In that way, both a lowercase z and an uppercase Z can share the same position in the bit field.
So, for an integer, if the values for a and Z were both set, the bits would look like
zyxwvutsrqponmlkjihgfedcba
00000010000000000000000000000001
We can use the bitwise OR operator to set the bit.
After the loop completes, the function returns if the phrasemask value is the same value as when all 26 bits are set, which is 67108863.
Source: Exercism javascript/pangram