2013-07-19 2 views
3

Привет и спасибо заранее за ответы, я пытался сделать первую задачу для PythonChallenge: http://www.pythonchallenge.com/pc/def/map.html и у меня есть comuple вопросов относительно кода. Я знаю, что этот код работает:код Цезаря - проблемы реализации в Python

import string 
letters = string.ascii_lowercase 
uletters = string.ascii_uppercase 
text = ("g fmnc wms bgblr rpylqjyrc gr zw fylb. rfyrq ufyr amknsrcpq ypc dmp. bmgle gr gl zw fylb gq glcddgagclr ylb rfyr'q ufw rfgq rcvr gq qm jmle. sqgle qrpgle.kyicrpylq() gq pcamkkclbcb. lmu ynnjw ml rfc spj.") 
for x in range(0, 26): 
    text = text.replace(letters[x-2], uletters[x]) 
    print(text.lower()) 

Я играл с кодом немного и вот мои наблюдения, в отношении которых у меня есть вопросы: 1. Когда я бегу:

text = text.replace(letters[x], uletters[x+2]) 

ошибки, такие как «trynslyte» вместо «translate». Почему этот сдвиг делает такое изменение? 2. Когда я изменил: uletters = string.ascii_uppercase к

uletters = string.ascii_lowercase 

появилась куча "Z" с и "у" с. Опять же, в чем дело?

Большое спасибо

ответ

4

Когда вы оцениваете letters[x-2] и x либо 0 или 1, вы в конечном итоге с letters[-1] или letters[-2], что в Python обращается к последней и предпоследней элементы, соответственно. Вот почему этот шаг работает. Однако индексы, которые больше, чем индекс последнего элемента, не имеют такого же эффекта, поэтому letters[x+2] не будет работать, если x слишком большой.

Что вам нужно сделать, это что-то вроде этого:

letters[(x+2)%len(letters)] 

Чтобы заставить это наматывается вокруг.

+0

Другой подход - просто написать 'letters = string.ascii_lowercase * 2' – kindall

0

Вы должны иметь дело с wraparound. Если x-2 меньше 0, вы получите ошибки.

+0

Нет, это направление в порядке. Это когда 'x + 2' слишком велик, что вызывает проблемы. –

+0

Вы правы. Я заметил, что это общий вопрос. – Jiminion

1

Лучший способ сделать это с помощью str.translate().

from string import ascii_lowercase as lc 

text = ("g fmnc wms bgblr rpylqjyrc gr zw fylb. rfyrq ufyr amknsrcpq ypc dmp. " 
     "bmgle gr gl zw fylb gq glcddgagclr ylb rfyr'q ufw rfgq rcvr gq qm jmle. " 
     "sqgle qrpgle.kyicrpylq() gq pcamkkclbcb. lmu ynnjw ml rfc spj.") 

print (text.translate(str.maketrans(lc, lc[2:] + lc[:2]))) 

Чтобы написать кодер, просто поменять местами аргументы maketrans() вокруг:

print (text.translate(str.maketrans(lc[2:] + lc[:2], lc))) 
0

Согласно Wikipedia, Цезарь шифра эти две математические congruencies:

E_n(x) ≡ (x + n) mod 26 
D_n(x) ≡ (x - n) mod 26 

Где E_n() является алгоритм шифрования, D_n(x) - алгоритм дешифрования, x - или зашифрованный текст, n - это ключ, а 26 - размер целочисленного кольца. Таким образом, самый простой способ написать программу для выполнения шифрования Цезаря - это реализовать вышеизложенное.

Единственное осложнение вы получите с делать это на компьютере, является тот факт, что вы работаете не на целых 0 через 25, но на двух диапазонах целых чисел, так как вы интерпретируете целые числа как символы из ASCII таблицы , Буквы верхнего регистра представляют собой целые числа 65 - 90, а строчные буквы - целые числа 97 - 122.

К счастью для вас, питон дает две функции, преобразующую ASCII символы в целые числа и обратно:

>>> ord('a') 
97 
>>> chr(97) 
'a' 

Вы можете использовать это, чтобы сохранить свои дела. Я собираюсь передать ord s в качестве аргументов по умолчанию, но ASCII на самом деле не изменится в ближайшее время. Тем не менее, это позволяет вам зашифровать разные символы без изменения кода.

def E(x, n, m=26, upper_ord=ord('A'), lower_ord=ord('a')): 
    if x.isupper(): 
     return chr(((ord(x) - upper_ord + n) % m) + upper_ord) 
    else: 
     return chr(((ord(x) - lower_ord + n) % m) + upper_ord) 

def D(x, n, m=26, upper_ord=ord('A'), lower_ord=ord('a')): 
    return E(x, -n, m, upper_ord, lower_ord) 

>>> E('b', 3) 
'e' 
>>> E('b', 25) 
'a' 
>>> E('b', -3) 
'y' 
>>> E('e', -3) 
'b' 
>>> E('Q', 15) 
'F' 
>>> plaintext = "The quick brown fox jumps over the lazy dog" 
>>> ciphertext = " ".join(map(lambda w: "".join(E(x, 2) for x in w), (word for word in 
sentence.split()))) 
>>> ciphertext 
'Vjg swkem dtqyp hqz lworu qxgt vjg ncba fqi' 
>>> decrypted = " ".join(map(lambda w: "".join(D(x, 2) for x in w), (word for word in 
ciphertext.split()))) 
>>> decrypted 
'The quick brown fox jumps over the lazy dog' 

Использование субиндексных смещений, на мой взгляд, надуманно. Математическая формула хорошо определена, поэтому просто используйте ее!

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