Неправильный вывод функции Python Caesar

Я слежу за 100 днями кода, и мне трудно понять, почему эта функция не работает должным образом.

alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","r","s","t","u","v","w","x","y","z",
            "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","r","s","t","u","v","w","x","y","z",
            "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","r","s","t","u","v","w","x","y","z"]

direction = input("Type 'encode' for Encode type 'decode' for Decode")
text = input("Type your message: \n").lower()
shift = int(input("Type the shift number: \n"))

def cesar(input_text,shift_ammount,which_direction):
    word = ""
    for letter in input_text:
        position = alphabet.index(letter)
        if which_direction == "decode":
            shift_ammount *= -1
        new_position = position + shift_ammount
        word += alphabet[new_position]
    print(f"the {which_direction}d text is {word}")

cesar(input_text=text,shift_ammount=shift,which_direction=direction)

Допустим, я пытаюсь расшифровать строку «BCD». Он возвращает «adc» вместо «abc». По какой-то причине он добавляет вместо вычитания ко второй позиции и возвращает неправильное значение. Любая помощь будет приветствоваться!

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
4
0
75
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Проблема в строке:

shift_ammount *= -1

Эта строка находится внутри цикла for, что означает, что shift_ammount будет изменять значение на каждой итерации. Поместите эту часть кода вне цикла for, чтобы получить правильный результат.

Обновленный код:

def cesar(input_text, shift_ammount, which_direction):
    word = ""
    if which_direction == "decode":
        shift_ammount *= -1
    for letter in input_text:
        position = alphabet.index(letter)
        new_position = position + shift_ammount
        word += alphabet[new_position]
    print(f"the {which_direction}d text is {word}")

Я проверил ваш код:

Если я кодирую abcdef со сдвигом 1, это дает мне bcdefg - это работает

Если я декодирую bcdefg со сдвигом 1, это дает мне adcfeh - каждая вторая буква сломана. Это связано с тем, что shift_amout *= -1 меняет направление в каждом цикле при декодировании.

Мое решение состоит в том, чтобы поставить if decode НАД циклом for, например

alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","r","s","t","u","v","w","x","y","z",
            "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","r","s","t","u","v","w","x","y","z",
            "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","r","s","t","u","v","w","x","y","z"]

direction = input("Type 'encode' for Encode type 'decode' for Decode: \n") #not part of the question, but you forgot the /n here 
text = input("Type your message: \n").lower()
shift = int(input("Type the shift number: \n"))

def cesar(input_text,shift_ammount,which_direction):
    if which_direction == "decode":
        shift_ammount *= -1

    word = ""
    for letter in input_text:
        position = alphabet.index(letter)
        new_position = position + shift_ammount
        word += alphabet[new_position]
    print(f"the {which_direction}d text is {word}")

cesar(input_text=text,shift_ammount=shift,which_direction=direction)

Проблема в вашем коде уже была решена другими в треде, поэтому я просто хотел бы сказать, что шифр Цезаря является прекрасным примером того, где str.translate является идеальным решением проблемы.

Используя str.maketrans в сочетании с offset, мы можем динамически перевести строку, используя пару dict-comprehensions:

import string
def cesar(text: str, offset: int, decode=False) -> str:
    alpha = string.ascii_lowercase
    if decode:
        cipher = {let: alpha[(idx - offset) % len(alpha)] for idx, let in enumerate(alpha)}
    else:
        cipher = {let: alpha[(idx + offset) % len(alpha)] for idx, let in enumerate(alpha)}
    return text.translate(str.maketrans(cipher))

x = "this is a test-string!"
newx = cesar(x, 1)
print(x)
print(newx)
print(cesar(newx, 1, decode=True))

Выход:

this is a test-string!
uijt jt b uftu-tusjoh!
this is a test-string!

Другие вопросы по теме