我试图编写一个函数decipher(s)
,该函数采用加密字符串旋转的字符串,然后返回原始的英文字符串。一个例子:
>>> decipher('Bzdrzq bhogdq? H oqdedq Bzdrzq rzkzc.')
'Caesar ciaapher? I preferr Caesaar saladd.'
它应该只接受一个字符串作为输入。以下是我写入加密的所有功能。我想知道如何使用rot
函数对letter_prob
中的所有可能选项进行评分,然后返回包含所有max
(最可能)字母出现的字符串。
def decipher(s):
lc= [rot for c in s]
options = [lc for n in range(26)]
scored_options = [[letter_prob(c),c] for c in options]
best_option = max(scored_options)
return best_option[1]
如何重写decipher
以便它返回一个包含所有最可能字符的字符串?
答案 0 :(得分:0)
我没有尝试过,但这样的事情应该有效:
def decipher(s):
options = [[rot(c, n) for c in s] for n in range(26)]
best_option = max(options, key=lambda x: sum(map(letter_prob, x)))
return ''.join(best_option)
options
将是每个组合的列表,如下所示:
[['B', 'z', 'd', 'r', 'z', 'q', ...], ['C', 'a', 'e', 's', 'a', 'r', ...], ...]
然后我们使用max
和key
参数来获得具有最高字母概率总和的选项。 ''.join()
将字符列表转换回字符串。
def decipher(s):
options = [[rot(c, n) for c in s] for n in range(26)]
scored_options = [[sum(map(letter_prob, x)), x] for x in options]
best_option = max(options)
return ''.join(best_option)
答案 1 :(得分:0)
我使用NumPy制作了代码的矢量化版本。我发现这一点更清楚了(虽然如果你之前没有看过NumPy,它起初会有点异国情调),对于长字符串它会更快:
import numpy as np
_a = ord('a')
_z = ord('z')
_A = ord('A')
_Z = ord('Z')
def encipher(s, n):
arr = np.fromstring(s, np.uint8)
rawcipher(arr, n)
return arr.tostring()
def rawcipher(arr, n):
lower = (arr >= _a) & (arr <= _z)
upper = (arr >= _A) & (arr <= _Z)
arr[lower | upper] += n
arr[lower & (arr > _z)] -= 26
arr[upper & (arr > _Z)] -= 26
letters = np.ones(128, dtype=np.float32)
letters[ord(' ')] = 0.1904
letters[ord('e')] = 0.1017
letters[ord('t')] = 0.0737
letters[ord('a')] = 0.0661
letters[ord('o')] = 0.0610
letters[ord('i')] = 0.0562
letters[ord('n')] = 0.0557
letters[ord('h')] = 0.0542
letters[ord('s')] = 0.0508
letters[ord('r')] = 0.0458
letters[ord('d')] = 0.0369
letters[ord('l')] = 0.0325
letters[ord('u')] = 0.0228
letters[ord('m')] = 0.0205
letters[ord('c')] = 0.0192
letters[ord('w')] = 0.0190
letters[ord('f')] = 0.0175
letters[ord('y')] = 0.0165
letters[ord('g')] = 0.0161
letters[ord('p')] = 0.0131
letters[ord('b')] = 0.0115
letters[ord('v')] = 0.0088
letters[ord('k')] = 0.0066
letters[ord('x')] = 0.0014
letters[ord('j')] = 0.0008
letters[ord('q')] = 0.0008
letters[ord('z')] = 0.0005
letters[_A:_Z+1] = letters[_a:_z+1]
def score(arr):
return letters[arr].sum()
def decipher(s):
arr = np.fromstring(s, np.uint8)
bestStr = None
bestScore = 0
for n in range(0, 26):
rawcipher(arr, 1)
thisScore = score(arr)
if thisScore > bestScore:
bestScore = thisScore
bestStr = arr.tostring()
return bestStr
请注意,Python中唯一的循环是在尝试所有可能的解密距离时从0到26。
我计时了,我的矢量化加密()需要3.6秒才能处理122 MB,而原始版本需要永久(我在40分钟后放弃了)。