3

您好,提前感谢您的回答,我正在尝试为 PythonChallenge 执行第一项任务:http: //www.pythonchallenge.com/pc/def/map.html 我有一些关于代码的问题。我知道这段代码有效:

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”和“y”出现了。再次,这是怎么回事?

非常感谢

4

4 回答 4

4

当你计算letters[x-2]andx是 0 或 1 时,你会得到letters[-1]or letters[-2],它在 Python 中分别访问最后一个和倒数第二个元素。这就是此步骤有效的原因。但是,大于最后一个元素的索引的索引没有相同的效果,所以太大letters[x+2]时不起作用x

你需要做的是这样的:

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

强制这种环绕。

于 2013-07-19T16:26:25.183 回答
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)))
于 2013-07-19T16:55:06.630 回答
0

你必须处理环绕。如果 x-2 小于 0,则会出现错误。

于 2013-07-19T16:28:30.200 回答
0

根据维基百科,凯撒密码是这两个数学一致性:

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表中的字符。大写字母是整数6590,小写字母是整数97122

幸运的是,python 为您提供了两个将 ASCII 字符转换为整数并返回的函数:

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

您可以利用它来保留您的案例。我将把ords 作为默认值传递给参数,但是 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'

在我看来,使用子索引偏移是人为的。数学公式是明确定义的,所以只需使用它!

于 2013-07-19T17:26:07.883 回答