我开始从一本书中学习一些加密技术,现在我有一项练习要求我从字符串中找出每个字符的频率:
这样的事情:
import collections
my_coded_string = """NTCGPDOPANFLHJINTOOFITOVJHJCTMMHIHEMTCPFDWTSOFSHTOGFWTE
TTJJTBTOOFSZOVEOCHCVCHPJHOCGTOHNQMTOCNTCGPDCGFCSTQMFBTO
FBGFSFBCTSHJCGTQMFHJCTYCXHCGFAHYTDDHAATSTJCBGFSFBCTSHJC
GTBHQGTSCTYCCGHONTCGPDQSTOTSWTOCGTMTCCTSASTRVTJBZHJCGTQ
MFHJCTYCFJDOPPJTBFJOTFSBGAPSCGTQMFHJCTYCASPNFIHWTJBHQGT
SCTYCEZBPNQFSHJICGTASTRVTJBZPATFBGMTCCTSFIFHJOCCGTLJPXJ
BPNNPJASTRVTJBZHJCGTVJDTSMZHJIMFJIVFIT"""
letters = collections.defaultdict(float)
for letter in my_coded_string:
letters[letter] += 1
d_descending = OrderedDict(sorted(letters.items(), key=lambda x: x[-1], reverse=True))
print d_descending
这将返回类型float
的字典,其中包含所有键及其频率(按降序排列)。到目前为止一切都那么好,没什么可怕的。
输出:
([
('T', 57.0), ('C', 40.0), ('J', 29.0), ('F', 27.0), ('H', 26.0), ('S', 23.0), ('G', 22.0), ('O', 20.0), ('B', 16.0),
('P', 15.0), ('M', 12.0), ('A', 10.0), ('N', 10.0), ('I', 9.0), ('Q', 9.0), ('D', 8.0), ('V', 8.0), ('Y', 6.0),
('Z', 6.0), ('E', 4.0), ('W', 4.0), ('R', 3.0), ('L', 2.0), ('X', 2.0)
])
现在,他们说为了解码这个字符串,我必须将这些频率与它们提供的频率进行比较,这似乎是英语中每个字符的预期频率。
现在,我遇到的问题是:我怎样才能更换最常出现的字母T
的所有出现,字母E
是第一个常用的英文字母,然后是{{ 1}}与C
等等?
在某些时候,当我用T
替换T
时,我会有57 E
秒,但我还会剩下E
秒。有什么想法吗?
答案 0 :(得分:1)
如果您还为预期英语的映射创建OrderedDict
语言(递减顺序),您将能够创建一个
第二个dict
,可用于将my_coded_string
翻译成一个
迭代。
让我们说预期的英语映射称为freqs
:
translate_table = dict(zip(d_descending, freqs))
my_string = ''.join([translate_table[c] for c in my_coded_string])
假设您还想处理换行符(\n
),这里有一个完整的代码:
import collections
import itertools
freqs = collections.OrderedDict([
('e', 12.702), ('t', 9.056), ('a', 8.167), ('o', 7.507),
('i', 6.749), ('n', 6.749), ('s', 6.327), ('h', 6.094),
('r', 5.987), ('d', 4.253), ('l', 4.052), ('c', 2.782),
('u', 2.758), ('m', 2.406), ('w', 2.360), ('f', 2.228),
('g', 2.015), ('y', 1.974), ('p', 1.929), ('b', 1.492),
('v', 0.978), ('k', 0.772), ('j', 0.153), ('x', 0.150),
('q', 0.095), ('z', 0.074)])
my_coded_string = """NTCGPDOPANFLHJINTOOFITOVJHJCTMMHIHEMTCPFDWTSOFSHTOGFWTE
TTJJTBTOOFSZOVEOCHCVCHPJHOCGTOHNQMTOCNTCGPDCGFCSTQMFBTO
FBGFSFBCTSHJCGTQMFHJCTYCXHCGFAHYTDDHAATSTJCBGFSFBCTSHJC
GTBHQGTSCTYCCGHONTCGPDQSTOTSWTOCGTMTCCTSASTRVTJBZHJCGTQ
MFHJCTYCFJDOPPJTBFJOTFSBGAPSCGTQMFHJCTYCASPNFIHWTJBHQGT
SCTYCEZBPNQFSHJICGTASTRVTJBZPATFBGMTCCTSFIFHJOCCGTLJPXJ
BPNNPJASTRVTJBZHJCGTVJDTSMZHJIMFJIVFIT"""
def translate(coded):
coded_lines = coded.split('\n')
letters = collections.defaultdict(float)
for letter in itertools.chain(*coded_lines):
letters[letter] += 1
mapping = dict(zip(
(i[0] for i in sorted(letters.items(),
key=lambda x: x[-1], reverse=True)),
freqs.keys()))
return '\n'.join(''.join(mapping[letter] for letter in line)
for line in coded_lines)
print(translate(my_coded_string))