Задать вопрос
Ответы пользователя по тегу Python
  • Как правильно написать код на Python для шифра "Цезарь"?

    @Vorono4ka
    У Rsa97 отличная идея с алфавитом. Мне захотелось написать код с её реализацией.

    У этой идеи есть небольшой нюанс (отнюдь, не минус, а порой даже плюс, если говорить о шифровании): без правильного алфавита расшифровать текст сразу не получится. Если это не нравится, то можно использовать для каждого языка свой алфавит, а не смешивать их воедино. Тогда алгоритм станет более похожим на классический шифр Цезаря, а значит и точный алфавит знать дешифровщику знать не нужно.

    Если уходить от задачи с шифром Цезаря, можно перемешать алфавит любым идемпотентным алгоритом (чтобы каждый раз получать одинаковый результат). Тогда шифр станет более надёжным.

    А если нет необходимости читать старые данные по прошествии времени, то можно вовсе менять ключ, по которому перемешивается алфавит, каждый день и получить этакую "Энигму".

    В C, Java и других языках понадобится следующая формула для приведения shift в нужные границы (0 ≤ shift < len(alphabet)):
    shift = (shift % len(alphabet) + len(alphabet)) % len(alphabet)


    Первый modulo нужен для ограничения сдвига размером алфавита. Сложение результата с длиной алфавита необходимо для получения неотрицательного числа.

    В Python же будет достаточно этого (см. как реализован modulo в Python):
    shift %= len(alphabet)  # Или shift = shift % len(alphabet)


    Но так как при индексации уже берется modulo, здесь никак не нужно обрабатывать shift заранее.

    import string
    
    alphabet = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя" 
    alphabet += alphabet.upper()
    alphabet += string.ascii_letters
    
    # Также можно добавить к алфавиту string.punctuation и string.digits
    
    def caesar_cipher(text: str, shift: int) -> str:
        return "".join(
            alphabet[(alphabet.index(char) + shift) % len(alphabet)] if char in alphabet else char 
            for char in text
        )
    
    cipher = caesar_cipher("Привет, мир! Hello, world!", 46)
    text = caesar_cipher(cipher, -46)  # Или len(alphabet) - 46
    print(f"{cipher}\n{text}")


    Итого получаем рабочий алгоритм и результат:
    DЭХОСЯ, ЩХЭ! ъYеез, пзкеX!
    Привет, мир! Hello, world!
    Ответ написан
    Комментировать