2017-02-02 4 views
0

Итак, я пытаюсь сделать код, который будет сдвигать каждую букву словом на несколько букв в алфавите (обертывание для конца). Например, если я хочу сдвинуть на 2, и я ввешу CBE, я должен получить AZC. или ДЖОН в HMFL. Я получил код, чтобы работать только одна буква, и мне интересно, если есть способ сделать вложенный цикл для питона (который работает?)Реализация алгоритма шифрования Цезаря в Python

def move(word, shift): 
    alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ" 
    original = "" 
    for letter in range(26, len(alphabet)): 
    if alphabet[letter] == word: #this only works if len(word) is 0, I want to be able to iterate over the letters in word. 
     original += alphabet[letter-shift] 
    return original 
+0

http://eddmann.com/posts/implementing-rot13-and-rot-n-caesar-ciphers-in-python/ – dabadaba

+0

Каким образом делает эта работа за 1 письмо? –

+0

Ну, это просто работает для одной буквы, потому что вы варьируетесь от '26', поэтому только один раз над алфавитом, и условие будет соответствовать только одному. –

ответ

1
A_VAL = ord('a') 

def move(word, shift): 
    new_word = "" 
    for letter in word: 
     new_letter = ord(letter) - shift 
     new_word += chr(new_letter) if (new_letter >= A_VAL) else (26 + new_letter) 
    return new_word 

Обратите внимание, что это будет работать только для строчных слов , Как только вы начнете смешивать буквы верхнего и нижнего регистра, вам нужно будет проверить их. Но это начало. Я отказался от идеи вашего вложенного цикла, потому что вам следует избегать таких, если это вообще возможно.

2

Не нашли письмо в алфавите , что способ - найти его с помощью операции индекса. Пусть символ быть буква вопрос:

alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 
... 
char_pos = alphabet.index(char) 
new_pos = (char_pos - shift) % len(alphabet) 
new_char = alphabet[new_pos] 

Как только вы поймете это, вы можете свернуть эти три строки в одной строке.

Теперь, чтобы сделать его работать на слово целиком ...

new_word = "" 
for char in word: 
    # insert the above logic 
    new_word += new_char 

Вы можете поместить все эти кусочки вместе?

Вам по-прежнему понадобится ваш чек, чтобы увидеть, что char - это письмо. Кроме того, если вам интересно, вы можете создать понимание списка для всех переведенных символов и применить '' .join(), чтобы получить новое слово.

Например ...

Если буква в алфавите (если символ в алфавите), сдвиг заданного расстояния и получить новое письмо, обернув вокруг конца, если это необходимо (% 26). Если это не прописная буква, используйте оригинальный символ.

Составьте список всех этих переводов, а затем присоедините их к строке. Верните эту строку.

def move(word, shift): 
    alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 
    return ''.join([alphabet[(alphabet.find(char) - shift) % 26] 
       if char in alphabet else char 
       for char in word]) 

print move("IBM", 1) 
print move("The 1812 OVERTURE is COOL!", 13) 

Выход:

HAL 
Ghe 1812 BIREGHER is PBBY! 
+0

Ничего себе, это намного элегантнее, чем я придумал. – Woody1193

5

Вы могли бы начать, как этот

def move(word, shift): 
    alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" 
    return "".join([alphabet[alphabet.find(i)-shift] for i in word]) 

В основном, этот список понимание создает список отдельных букв. Затем индекс буквы в алфавите найден методом .find. (Index-shift) - это желаемый новый индекс, который извлекается из алфавита. Полученный список снова соединяется и возвращается.

Обратите внимание, что это явно не работает с строчными вводами строк (если вы хотите использовать метод str.upper). Собственно, слово должно состоять только из букв, присутствующих в алфавите. Для предложений подход должен относиться к пробелам по-разному.

+0

Это не работает, скажем, «B» и сдвиг 4. Замените ** find ** на ** rfind **, и я думаю, что у вас есть суть решения. – Prune

+0

@Prune Можете ли вы объяснить, почему, пожалуйста? Ожидаемый результат: «X» в этом случае нет? – Tristan

+0

Я коротко забыл о правостороннем индексировании; он работает для сдвигов <52. Тем не менее, он получит индексную ошибку для чего-либо из вашего диапазона с двойным алфавитом. Если вы зависите от значения <26, то вы можете удалить второй алфавит. – Prune

0

Вы можете использовать: chr() дать вам символ для номера ascii, ord() дать вам номер ascii для соответствующего символа.

Вот старый проект Vigenere:

def code_vigenere(ch,cle): 
    text = ch.lower() 
    clef = cle.lower() 
    L = len(cle) 
    res = '' 

    for i,l in enumerate(text): 
     res += chr((ord(l) - 97 + ord(cle[i%L]) - 97)%26 +97) 

    return res 
Смежные вопросы