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
, thena
will result in0
, because97
minus97
equals0
.z
would result in25
, because122
minus97
equals25
. Soa
would have1
shifted left 0 places (so not shifted at all) andz
would have1
shifted left 25 places. - If the upper-cased letter is subtracted by
A
, thenA
will result in0
, because65
minus65
equals0
.Z
would result in25
, because90
minus65
equals25
. SoA
would have1
shifted left 0 places (so not shifted at all) andZ
would have1
shifted 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.