This program asks the user to input a List of words. It then returns a list of encrypted words, and a second list which specifies the numerical shifts used to encrypt those words. The idea was obtained from https://www.khanacademy.org/computing/computer-science/cryptography/crypt/v/one-time-pad
import random
def rotate_letter(letter, number):
if letter == ' ':
return letter
if letter.islower():
start = ord('a')
elif not letter.islower():
start = ord('A')
normal_shift = ord(letter) - start
new_letter = start + (normal_shift + number) % 26
return chr(new_letter)
def avoid(letter):
avoid = ' ,!?¿,*+-%/@1234567890'
for i in avoid:
if i == letter:
return False
return True
def rotate_word(word):
new_word = ''
random_series = []
for letter in word:
if avoid(letter):
random_number = random.randint(1,26)
new_letter = rotate_letter(letter, random_number)
new_word += new_letter
random_series.append(random_number)
else:
new_word += letter
return (new_word, random_series)
def shift(words):
index = 0
encrypted_words = []
random_shifts = []
while index < len(words):
(new_word, random_series) = rotate_word(words[index])
encrypted_words.append(new_word)
random_shifts.append(random_series)
index += 1
return (encrypted_words, random_shifts)
def get_input():
words = []
while True:
user = (input('Input words to encrypt. Done when ready \n' ))
if user == 'Done' or user == 'done':
return words
words.append(user)
def start():
words = get_input()
encrypted_words = []
random_shifts = []
(encrypted_words, random_shifts) = shift(words)
print('UNENCRYPTED WORDS', words)
print('ENCRYPTED WORDS', encrypted_words)
print('RANDOM SHIFTS', random_shifts)
start()
1 Answer 1
Your function avoid
is quite unnecessary and also confusing. I would expect avoid('@')
to return True
. When you store the letters as a global constant and as set, you should gain some speed (both because it does not have to be reconstructed again and again and because membership testing is very fast for a set
. I replaced your function with letter not in letters_avoid
.
Whenever you are doing string addition in Python, you are probably doing something wrong. This is because strings are immutable so for every addition a new string has to be created and the content of the strings to be added needs to be copied. This is quite slow. Rather, use a list
to accumulate the letters of new_word
and str.join
them at the end.
When returning a tuple
, the ()
are implicit. You can just write return a, b
.
When iterating over words
, you should just directly iterate over it, instead of its indices.
Using str.lower
cuts down the double comparison if user == 'Done' or user == 'done'
to if user.lower() == 'done':
.
You should call your code with a if __name__ == '__main__':
guard to allow importing your functions from another script without executing the whole script.
Final code:
import random
letters_avoid = set(' ,!?¿,*+-%/@1234567890')
def rotate_letter(letter, number):
if letter == ' ':
return letter
if letter.islower():
start = ord('a')
elif not letter.islower():
start = ord('A')
normal_shift = ord(letter) - start
new_letter = start + (normal_shift + number) % 26
return chr(new_letter)
def rotate_word(word):
new_word = []
random_series = []
for letter in word:
if letter not in letters_avoid:
random_number = random.randint(1, 26)
new_word.append(rotate_letter(letter, random_number))
random_series.append(random_number)
else:
new_word.append(letter)
return "".join(new_word), random_series
def shift(words):
encrypted_words = []
random_shifts = []
for word in words:
new_word, random_series = rotate_word(word)
encrypted_words.append(new_word)
random_shifts.append(random_series)
return encrypted_words, random_shifts
def get_input():
words = []
while True:
user = input('Input words to encrypt. Done when ready \n')
if user.lower() == 'done':
return words
words.append(user)
def start():
words = get_input()
encrypted_words, random_shifts = shift(words)
print('UNENCRYPTED WORDS', words)
print('ENCRYPTED WORDS', encrypted_words)
print('RANDOM SHIFTS', random_shifts)
if __name__ == "__main__":
start()
input
. \$\endgroup\$