Проблема со смещением в шифре цезаря
Стандартный шифр Цезаря. Проблема в расчетной формуле, если задано смещение больше длины алфавита. Ожидаю, что при смещении 1, буква А станет Б, а при смещении 34 буква Я станет А. Не пойму что напутал в цифрах.
eng_lower_alphabet = 'abcdefghijklmnopqrstuvwxyz'
eng_upper_alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
rus_lower_alphabet = "абвгдежзийклмнопрстуфхцчшщъыьэюя"
rus_upper_alphabet = "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"
symbol = [" ", ",", ".", "!", "?"]
def shift(i, offset):
if i.isalpha():
if i in eng_lower_alphabet:
print(eng_lower_alphabet[(ord(i) + (offset % 26)) - 97])
if i in rus_lower_alphabet:
print(rus_lower_alphabet[(ord(i) + (offset % 33)) - 1072])
if i in eng_upper_alphabet:
print(eng_upper_alphabet[(ord(i) + (offset % 26)) - 65])
if i in rus_upper_alphabet:
print(rus_upper_alphabet[(ord(i) + (offset % 33)) - 1040])
print("Введите букву")
phrase = input()
shift(phrase, 1088)
Ошибка:
IndexError Traceback (most recent call last)
<ipython-input-99-1f3e9ddd2432> in <module>
18 print("Введите букву")
19 phrase = input()
---> 20 shift(phrase, 1088)
21
22
<ipython-input-99-1f3e9ddd2432> in shift(i, offset)
10 print(eng_lower_alphabet[(ord(i) + (offset % 26)) - 97])
11 if i in rus_lower_alphabet:
---> 12 print(rus_lower_alphabet[(ord(i) + (offset % 33)) - 1072])
13 if i in eng_upper_alphabet:
14 print(eng_upper_alphabet[(ord(i) + (offset % 26)) - 65])
IndexError: string index out of range
Ответы (2 шт):
У вас в rus_lower_alphabet и rus_upper_alphabet всего 32 буквы, поэтому надо брать остаток от деления на 32, а не на 33, как у вас.
offset % 33 --> offset % 32
1088 % 33 = 32, поэтому индекс выходит за границу списка. Диапазон корректных индексов для списка из 32 элементов: [0:31].
Но и это не всё. Остаток нужно брать уже после всех вычислений. И константы лучше вычислять, а не жёстко забивать в код в данном случае. Т.е. код должен выглядеть так (на примере одного из алфавитов):
print(eng_lower_alphabet[(ord(i) - ord(eng_lower_alphabet[0]) + offset) % len(eng_lower_alphabet)])
В принципе, можно вынести этот код в отдельную функцию и потом применять эту функцию сколько нужно раз с нужными аргументами.
Для rus_lower_alphabet
if (rus_lower_alphabet.index(i) + (offset % 32)) <= 31:
print(rus_lower_alphabet[(rus_lower_alphabet.index(i) + (offset % 32))])
else:
print(rus_lower_alphabet[32 - (rus_lower_alphabet.index(i) + (offset % 32))])
Или
print(rus_lower_alphabet[(rus_lower_alphabet.index(i) + (offset % 32)) % 32])