Цезарь - python
Помогите решить задачу:
Напишите функцию encrypt_caesar(msg, shift), которая кодирует сообщение шифром Цезаря и возвращает его. Шифр Цезаря заменяет каждую букву в тексте на букву, которая отстоит в алфавите на некоторое фиксированное число позиций. В функцию передается сообщение и сдвиг алфавита. Если сдвиг не указан, то пусть ваша функция кодирует сдвиг алфавита на 3 позиции: А →Г, Б →Д, В →Е, … Э →А, Ю →Б, Я →В Все символы, кроме русских букв должны остаться неизменными. Маленькие буквы должны превращаться в маленькие, большие — в большие. Напишите также функцию декодирования decrypt_caesar(msg, shift), также использующую сдвиг по умолчанию. При написании функции декодирования используйте вашу функцию кодирования.
Код:
alpha = ' abcdefghijklmnopqrstuvwxyz'
n = int(input())
s = input().strip()
res = ''
for c in s:
res += alpha[(alpha.index(c) + n) % len(alpha)]
print('Result: "' + res + '"')
Ожидаемый результат Зг кзугефхецих фгогх Щикгуя! Да здравствует салат Цезарь!
Вывод Makefile:5: recipe for target 'run' failed
Ответы (3 шт):
Вы пишете:
Ожидаемый результат Зг кзугефхецих фгогх Щикгуя! Да здравствует салат Цезарь!
но это противоречит условию:
Шифр Цезаря заменяет каждую букву в тексте на букву, которая отстоит в алфавите на некоторое фиксированное число позиций
Смотрите сами: Д -> З - смещение на 4 позиции, а -> г - смещение на 3 позиции, з -> к - 3 позиции, д -> з - 4 позиции. Ну, вы поняли.
Я сделал смещение на фиксированое число позиций.
Вот вариант с рекурсией:
small_symbols = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"
big_symbols = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"
def shift(text, symbols, n):
index = symbols.find(text)
if index + n < len(symbols):
return symbols[index + n]
else:
return symbols[(index + n) % len(symbols)]
def back_shift(text, symbols, n):
index = symbols.find(text)
if index - n >= 0:
return symbols[index - n]
else:
return symbols[(index - n) % len(symbols)]
def encrypt(text, n = 3, i = 0, res = ""):
if (len(res) == len(text)): return res
if text[i].isupper():
res += shift(text[i], big_symbols, n)
elif text[i].islower():
res += shift(text[i], small_symbols, n)
else:
res += text[i]
return encrypt(text, n, i+1, res)
def decrypt (text, n = 3, i = 0, res = ""):
if (len(res) == len(text)): return res
if text[i].isupper():
res += back_shift(text[i], big_symbols, n)
elif text[i].islower():
res += back_shift(text[i], small_symbols, n)
else:
res += text[i]
return decrypt(text, n, i+1, res)
str = encrypt(input())
print(str)
print(decrypt(str))
И без неё:
small_symbols = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"
big_symbols = "АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"
def shift(text, symbols, n):
index = symbols.find(text)
if index + n < len(symbols):
return symbols[index + n]
else:
return symbols[(index + n) % len(symbols)]
def back_shift(text, symbols, n):
index = symbols.find(text)
if index - n >= 0:
return symbols[index - n]
else:
return symbols[(index - n) % len(symbols)]
def encrypt(text, n = 3):
res = ""
for i in range(0, len(text)):
if text[i].isupper():
res += shift(text[i], big_symbols, n)
elif text[i].islower():
res += shift(text[i], small_symbols, n)
else:
res += text[i]
return res
def decrypt (text, n = 3):
res = ""
for i in range(0, len(text)):
if text[i].isupper():
res += back_shift(text[i], big_symbols, n)
elif text[i].islower():
res += back_shift(text[i], small_symbols, n)
else:
res += text[i]
return res
str = encrypt(input())
print(str)
print(decrypt(str))
Рассмотрим подробнее второй вариант. Сначала я создал списки из русских букв верхнего и нижнего регистра. Далее идёт функция смещения (shift). Зачем функция? Чтобы не копипастить код, с различием только в списке букв для поиска.
Сама функция принимает на вход одну букву (ну, или надеется, что вы дадите 1 букву), список букв для поиска, смещение. Далее вычисляет индекс этой буквы в списке (метод find), потом проверяет, можно ли получить букву, смещённую на n позиций. Если да - возвращает эту букву. Если же нет, определяет букву по принципу Э →А, Ю →Б, Я →В и т. д. и всё равно возвращает изменённую букву.
Функция back_shift делает тоже самое, только наоборот.
И теперь интересное - функция encrypt. Она получает текст и смещение.
Зачем n=3, можно же просто n? Нельзя. Благодаря этому функция использует стандартное смещение (3), если не указано пользовательское. Иначе вы бы получали ошибку:
TypeError: encrypt() missing 1 required positional argument: 'n'
Далее запускается цикл for, который проходится по всей строке. Он проверяет - если буква text[i] является маленькой - запускает функцию смещения, как для маленькой буквы. И соответственно также для больших букв. (Вот он, плюс использовать функцию! Иначе пришлось бы копировать кусок кода от шифрования маленьких букв и менять список на список больших. И так каждый раз, когда нужно поменять регистр или язык символов... С функцией можно просто передавать, как аргумент список других букв.)
И если буква не является ни большой, ни маленькой - значит это другой символ (пробел, точка, кавычки и т.д.). В таком случае ничего не меняется.
И расшифровка, тоже самое, только наоборот (где-то я это уже видел...)
А вот и часть кода, которая выполнится при старте программы (наконец-то мы её нашли!). Она просто ждёт ввода пользователя - запускает шифрование, а потом дешифрирование.
P.S - пример с рекурсией выглядит красиво, но будет работать чуть медленнее, и при строках не больше 2000 - 3000 символов. (Такие уж в python ограничения).
у вас res строка а вы прибавляете число
Traceback (most recent call last):
File "D:\Python_Project\курс 2 урок 5 функции с переменным числом аргументов\Цезарь.py", line 53, in <module>
encrypted = encrypt_caesar(msg, shift)
File "D:\Python_Project\курс 2 урок 5 функции с переменным числом аргументов\Цезарь.py", line 26, in encrypt_caesar
res += shift(text[i], big_symbols, n)
TypeError: 'int' object is not callable
def encrypt_caesar(msg, shift=3):
small_symbols1 = "абвгдежзийклмнопрстуфхцчшщъыьэюя"
big_symbols1 = "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ"
shift = shift % len(small_symbols1)
small_symbols2 = small_symbols1[shift:] + small_symbols1[:shift]
big_symbols2 = big_symbols1[shift:] + big_symbols1[:shift]
translation = msg.maketrans(small_symbols1 + big_symbols1, small_symbols2 + big_symbols2)
return msg.translate(translation)
def decrypt_caesar(msg, shift=3):
return encrypt_caesar(msg, -1 * shift)