Я слежу за 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». По какой-то причине он добавляет вместо вычитания ко второй позиции и возвращает неправильное значение. Любая помощь будет приветствоваться!
Проблема в строке:
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!