确定密文的字母频率

4 投票
3 回答
15281 浏览
提问于 2025-04-15 12:14

我正在尝试制作一个工具,用来找出某种密码文本中字母的出现频率。假设这些字母都是小写的a-z,没有数字。这个编码的信息保存在一个txt文件里。

我想写一个脚本,帮助破解替换密码或者可能的换位密码。

到目前为止的代码:

cipher = open('cipher.txt','U').read()
cipherfilter = cipher.lower()
cipherletters = list(cipherfilter)

alpha = list('abcdefghijklmnopqrstuvwxyz')
occurrences = {} 
for letter in alpha:
    occurrences[letter] = cipherfilter.count(letter)
for letter in occurrences:
    print letter, occurrences[letter]

现在这段代码只显示了某个字母出现的次数。我该如何打印出这个文件中所有字母的频率呢?

3 个回答

2

如果你想知道一个字母 c 的 相对频率,你需要把字母 c 出现的次数除以输入文本的总长度。

比如,按照亚当的例子:

s = "andnowforsomethingcompletelydifferent"
n = len(s) # n = 37

然后把每个字母的绝对频率存储在

dict[letter]

我们可以通过以下方式得到相对频率:

from string import ascii_lowercase # this is "a...z"
for c in ascii_lowercase:
    print c, dict[c]/float(n)

把这些信息整合在一起,我们就能得到类似这样的结果:

# get input
s = "andnowforsomethingcompletelydifferent"
n = len(s) # n = 37

# get absolute frequencies of letters
import collections
dict = collections.defaultdict(int)
for c in s:
    dict[c] += 1

# print relative frequencies
from string import ascii_lowercase # this is "a...z"
for c in ascii_lowercase:
    print c, dict[c]/float(n)
11

现代的方法:

from collections import Counter

string = "ihavesometextbutidontmindsharing"
Counter(string)
#>>> Counter({'i': 4, 't': 4, 'e': 3, 'n': 3, 's': 2, 'h': 2, 'm': 2, 'o': 2, 'a': 2, 'd': 2, 'x': 1, 'r': 1, 'u': 1, 'b': 1, 'v': 1, 'g': 1})
17
import collections

d = collections.defaultdict(int)
for c in 'test':
    d[c] += 1

print d # defaultdict(<type 'int'>, {'s': 1, 'e': 1, 't': 2})

来自一个文件:

myfile = open('test.txt')
for line in myfile:
    line = line.rstrip('\n')
    for c in line:
        d[c] += 1

我们要感谢和赞美这个聪明的 defaultdict 容器。要不然我们可能就得做一些傻事,比如这样:

s = "andnowforsomethingcompletelydifferent"
d = {}
for letter in s:
    if letter not in d:
        d[letter] = 1
    else:
        d[letter] += 1

撰写回答