密文字母频繁替换:按值比较两个字典的dict键并改变tex

2024-04-27 12:40:07 发布

您现在位置:Python中文网/ 问答频道 /正文

我已经看过类似的主题,但没有一个解决方案能与我正在努力实现的目标相比。在

我有一个密码文本,需要根据每个字母在文本中出现的频率进行简单的字母替换。我已经有一个函数来规范化文本(小写,无字母字符,不,计数字母出现的次数,然后得到每个字母的相对频率。字母是字典中的键,频率就是值。在

我在一个单独的字典中也有A-Z的预期字母频率(k=letter,v=frequency),但是我对下一步要做什么有点困惑。在

我想我需要做的是取标准化的密文,预期的字母freq dict[d1]和密文freq dict[d2],然后按如下方式对它们进行迭代(部分psuedocode):

for word in text:
    for item in word:
        for k,v in d2.items():
            if d2[v] == d1[v]:
                replace any instance of d2[k] with d1[k] in text
    decoded_text=open('decoded_text.txt', 'w')
    decoded_text.write(str('the decoded text')

在这里,我想获取文本并说“如果d2中的值与d1中的值匹配,则用文本中的d1[k]替换d2[k]的任何实例”。在

我意识到我在那里一定犯了一些基本的python逻辑错误(我在python方面相对较新),但是我走对了吗?在

提前谢谢

更新:

谢谢你提出的所有有用的建议。我决定尝试一下karlknechtel的方法,在代码中做一些修改。但是,我仍然有问题(完全在我的实现中)

我做了一个解码函数来获取有问题的密文文件。这将调用先前生成的count函数,该函数返回一个字典(字母:频率为浮子)。这意味着“makeuppercase version”代码将无法工作,因为k和v不是float,不能将.upper作为属性。因此,调用这个decode函数返回密文字母频率,然后返回密文本身,仍然是编码的。在

^{pr2}$

Tags: 函数textin文本for字典字母dict
3条回答

首先,请注意,除非你的信息很长,否则频率不太可能与你完全匹配。所以你可能需要做一些手动调整来得到确切的信息。但是如果频率足够接近。。。在

你可以得到两个字典(字母)的键,按它们的值(频率)排序:

letters_in_frequency_order = sorted(d1.keys(), key=lambda x: d1[x])

然后把它们变成线:

^{pr2}$

然后使用它们来翻译字符串:

import string
transtable = string.maketrans(cypher_alphabet, normal_alphabet)
cyphertext.translate(transtable)

你并不真的想做你想做的事情,因为样本中字符的频率通常与参考数据中精确的频率分布不匹配。你真正要做的是找到最常见的字符并将其替换为“e”,其次是“t”,以此类推。在

所以我们要做的是:

  1. (我想你已经可以做这部分了)构建一个密文中实际字母频率的字典。

  2. 我们定义了一个函数,它接受{letter:frequency}字典并按频率顺序生成字母列表。

  3. 类似地,我们有一个最常见的英文字母的顺序。

  4. 假设样本中最常见的字母对应于英语中最常见的字母,依此类推:我们创建一个新字典,将第一个列表中的字母映射为第二个列表中的字母。(我们还可以创建一个与str.translate一起使用的翻译表。)我们将制作同一词典的大写和小写版本(我假设您的原始词典只有小写)并将它们合并在一起。

  5. 我们使用这个映射来翻译密码文本,而不使用其他字符(空格、标点符号等)。

因此:

# 2.
import operator
def sorted_histogram(a_dict):
  return [
    x[1] # the value
    for x in sorted(a_dict.items(), key=operator.itemgetter(1))
    # of each dict item, sorted by value (i.e. the [1] element of each item).
  ]

# 3.
english_histogram = sorted_histogram(english_dict)
cipher_histogram = sorted_histogram(cipher_dict)

# 4.
# Make the lowercase version
mapping = dict(zip(english_histogram, cipher_histogram))
# Make the uppercase version, and merge it in at the same time.
mapping.update(dict(
  (k.upper(), v.upper()) for (k, v) in zip(english_histogram, cipher_histogram)
))

# 5.
translated = ''.join( # make this list of characters, and string them together:
  mapping.get(c, c) # the mapped result, if possible; otherwise the original
  for c in cipher
)

# 6. Do whatever you want with 'translated' - write to file, etc.
#!/usr/bin/env python
from operator import itemgetter
import string

def frequency(text):
    d = {}
    for letter in text:
        try:
            d[letter] += 1
        except:
            d[letter] = 1
    return d

def alphabet():
    for alpha in string.letters: yield alpha

def cipher(text):
    expected = frequency(text)
    flist = sorted(expected.iteritems(), key=itemgetter(1), reverse=True)
    alphabet_generator = alphabet()
    for char, freq in flist:
        text = text.replace(char, alphabet_generator.next())
    return (text, expected)

def decipher(text, expected):
    nal = [ x[0] for x in sorted(expected.iteritems(), key=itemgetter(1), \
            reverse=True) ]
    normal_alphabet = ''.join(nal)
    transtable = string.maketrans(string.letters[:len(normal_alphabet)], \
                                  normal_alphabet)
    return text.translate(transtable)

用法:

^{pr2}$

相关问题 更多 >