A_LCASE = 97
A_UCASE = 65
ALL_26_BITS_SET = 67108863
def is_pangram(sentence):
letter_flags = 0
for letter in sentence:
if 'a' <= letter <= 'z':
letter_flags |= 1 << ord(letter) - A_LCASE
elif 'A' <= letter <= 'Z':
letter_flags |= 1 << ord(letter) - A_UCASE
return letter_flags == ALL_26_BITS_SET
This solution uses the ASCII value of the letter to set the corresponding bit position. First, some constant values are set.
Python doesn't enforce having real constant values, but using all uppercase letters is the naming convention for a Python constant. It indicates that the value is not intended to be changed.
These values will be used for readability in the body of the is_pangram
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
.
- The
for
loop loops through the characters of thesentence
. - Each letter is tested for being
a
throughz
orA
throughZ
. - If the lowercased 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 uppercased 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 a 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 OR operator to set the bit.
After the loop completes, the function returns True
if the letter_flags
value is the same value as when all of the rightmost 26
bits are set,
which is 67108863
.
Although this approach is usually very fast in some other languages, it is comparatively slow in Python.