public static class Isogram
{
public static bool IsIsogram(string word) {
int letter_flags = 0;
foreach (char letter in word)
{
if (letter >= 'a' && letter <= 'z')
{
if ((letter_flags & (1 << (letter - 'a'))) != 0)
return false;
else
letter_flags |= (1 << (letter - 'a'));
}
else if (letter >= 'A' && letter <= 'Z')
{
if ((letter_flags & (1 << (letter - 'A'))) != 0)
return false;
else
letter_flags |= (1 << (letter - 'A'));
}
}
return true;
}
}
This solution uses the ASCII value of the letter to set the corresponding bit position.
The string loops through its characters and looks for a character being a through z or A through Z.
The ASCII value for a is 97, and for z is 122.
The ASCII value for A is 65, and for Z is 90.
- If the lower-cased letter is subtracted by
a, thenawill result in0, because97minus97equals0.zwould result in25, because122minus97equals25. Soawould have1shifted left 0 places (so not shifted at all) andzwould have1shifted left 25 places. - If the upper-cased letter is subtracted by
A, thenAwill result in0, because65minus65equals0.Zwould result in25, because90minus65equals25. SoAwould have1shifted left 0 places (so not shifted at all) andZwould have1shifted left 25 places.
In that way, both a lower-cased z and an upper-cased Z can share the same position in the bit field.
So, for an unsigned thirty-two bit integer, if the values for a and Z were both set, the bits would look like
zyxwvutsrqponmlkjihgfedcba
00000010000000000000000000000001
We can use the bitwise AND operator to check if a bit has already been set.
If it has been set, we know the letter is duplicated and we can immediately return false.
If it has not been set, we can use the bitwise OR operator to set the bit.
If the loop completes without finding a duplicate letter (and returning false), the function returns true.
This approach may be considered to be more idiomatic of the C language than C#.
It is fast, but it only works with the ASCII alphabet.