Reputation: 335
Can anyone explain why "%26" is needed in the following code? The result seems the same without "%26". Code source enter link description here
def caesar_encrypt(realText, step):
outText = []
cryptText = []
uppercase = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
lowercase = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
for eachLetter in realText:
if eachLetter in uppercase:
index = uppercase.index(eachLetter)
crypting = (index + step) % 26
cryptText.append(crypting)
newLetter = uppercase[crypting]
outText.append(newLetter)
elif eachLetter in lowercase:
index = lowercase.index(eachLetter)
crypting = (index + step) % 26
cryptText.append(crypting)
newLetter = lowercase[crypting]
outText.append(newLetter)
return outText
code = caesar_encrypt('abc', 2)
print(code)
Upvotes: 0
Views: 68
Reputation: 51683
You need the %26
to avoid overshooting your list of mappings if the position of the original characters +step
would go out of bounds. This starts on position 0 again if you land after the last character.
The code you posted uses lots of searches over text, which takes quite some time.
It would be better to just "look up" what pos
a character has, add step
to that and then look up what character is assigned to this sum. You do not need a full upper- and lowercase mapping: you can test the input character and use .upper()
to create an upper case character from the lower case one.
# lowercase and uppercase ascii can be taken from constants out of string module
import string
# create a dict that comntains character -> info, only for lowercase
cryptDict = {ch:pos for pos,ch in enumerate(string.ascii_lowercase)}
# add the inverse mapping (pos ->character)
for k,v in cryptDict.items():
cryptDict[v] = k
def caesar_encrypt(realText, step):
outText = []
cryptText = []
for letter in realText:
# get what pos this letter is at
pos = cryptDict.get(letter,None) # gets None if character not in, f.e. 8
if pos is not None:
# you need % 26 here, in case your pos + step goes bigger then 26
# f.e. z = 25,step = 2 => 27 , you do not have any character thats
# mapped to 27,so you % 26 and use b which is mapped to 1
crypt = cryptDict[(pos + step)%26]
# fix casing if input was uppercase
if letter.isupper():
crypt = crypt.upper()
outText.append(crypt)
else:
outText.append(letter) # do not forget unmapped values
return outText
code = caesar_encrypt('abc', 2)
print(code) # ['c','d','e']
The cryptDict
looks like so:
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i',
9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r',
18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z',
'a': 0, 'c': 2, 'b': 1, 'e': 4, 'd': 3, 'g': 6, 'f': 5, 'i': 8, 'h': 7,
'k': 10, 'j': 9, 'm': 12, 'l': 11, 'o': 14, 'n': 13, 'q': 16, 'p': 15, 's': 18,
'r': 17, 'u': 20, 't': 19, 'w': 22, 'v': 21, 'y': 24, 'x': 23, 'z': 25}
Reference: - string.ascii_lowercase
Upvotes: 1