Problem overview
The method usesEveryLetter gets a String called sentence made of lowercase letters and spaces. It returns true when every letter from a to z appears at least once, and false otherwise. Spaces are not letters, and a letter may repeat.
The sentence "my jumpy dog fixed a big quiz with seven lucky parrots" contains all 26 letters, so the answer is true. In "six jumpy kittens quiz the brave fox and a wild hog" the letter c is missing, so the answer is false. "abc abc abc" has only three different letters, so it is false too.
Approach
Collect the different letters of the sentence in a set. A set keeps each letter once, no matter how many times it appears. If the sentence holds only lowercase letters and spaces, then having 26 different letters means having all of them.
Step by step
- Create an empty mutable set of
Charnamedletters. - Loop over the characters with
for (c <- sentence). AStringcan be looped over directly, and eachcis aChar. - Skip spaces with
if (c != ' '). A space is not a letter, so it must stay out of the set. - Add each letter with
letters += c. - Return
letters.size == 26. The comparison is alreadytrueorfalse.
The solution in Scala
class Solution {
def usesEveryLetter(sentence: String): Boolean = {
val letters = scala.collection.mutable.Set[Char]()
for (c <- sentence) {
if (c != ' ') {
letters += c
}
}
return letters.size == 26
}
}
A character is written with single quotes, ' ', while a string uses double quotes, " ". The loop variable c is a Char, so compare it with the character.
The size of the set is the number of different letters. For example, "abc abc abc" gives a set of 3 letters, which is why the third example is false.
Repeats cost nothing
In the first sentence, r appears several times (in "parrots" alone, twice). Each letters += c after the first leaves the set as it was. You never have to check "is it already there?" yourself, which is the main reason to reach for a set here. The loop also keeps working for the longest allowed sentence of 1,000 characters, since it makes one pass over the text.
Why 26 is enough
The statement promises lowercase English letters and spaces only. After the spaces are skipped, every member of the set is one of the 26 lowercase letters, so a set of size 26 cannot be missing any of them. If the input could hold digits or capitals, the size would no longer prove it, and you would test each letter of the alphabet instead.
Testing
The three examples return true, false and false (the tests print booleans in lowercase).
Another way
Instead of counting, ask about each letter of the alphabet:
val ok = ('a' to 'z').forall(sentence.contains(_))
This is true for the first sentence and false for the second. It also lets you find the missing letters: ('a' to 'z').filterNot(sentence.contains(_)) gives Vector(c) for the second sentence.
Edge cases and common mistakes
- Letting spaces into the set. The first sentence would then give a set of 27 values, and
letters.size == 26would sayfalsefor a sentence that has every letter. - Counting letters instead of different letters. A long sentence can still lack a letter; only the set size tells you how many are different.
- Using
=for the comparison. Use==; a single=is an assignment. - Writing
returnwith anifaround it. The comparison is already the answer.
