Python 凯撒密码解码器

Posted

技术标签:

【中文标题】Python 凯撒密码解码器【英文标题】:Python Caesar Cipher Decoder 【发布时间】:2012-06-03 06:11:13 【问题描述】:

在我的课程中,我的任务是创建一个 Caesar Cipher 解码器,该解码器接受输入字符串并使用字母频率找到可能的最佳字符串。如果不确定这有多大意义,请发布问题:

编写一个执行以下操作的程序。首先,它应该读取一行输入,即编码消息,由大写字母和空格组成。您的程序必须尝试使用​​移位 S 的所有 26 个可能值来解码消息;在这 26 条可能的原始消息中,打印出具有最高善意的一条。 为了您的方便,我们会为您预定义变量 letterGoodness,一个长度为 26 的列表,它等于上面频率表中的值

到目前为止我有这个代码:

x = input()
NUM_LETTERS = 26 #Can't import modules I'm using a web based grader/compiler
def SpyCoder(S, N):
    y = ""
    for i in S:
        x = ord(i)
        x += N
        if x > ord('Z'):
            x -= NUM_LETTERS
        elif x < ord('A'):
            x += NUM_LETTERS
        y += chr(x)
    return y  

def GoodnessFinder(S):
    y = 0
    for i in S:
        if x != 32:
            x = ord(i)
            x -= ord('A')
            y += letterGoodness[x]
    return y 

def GoodnessComparer(S):
    goodnesstocompare = GoodnessFinder(S)
    goodness = 0
    v = ''
    for i in range(0, 26):
        v = SpyCoder(S, i)
        goodness = GoodnessFinder(v)
        if goodness > goodnesstocompare:
            goodnesstocompare = goodness
    return v

y = x.split()
z = ''
for i in range(0, len(y)):
    if i == len(y) - 1:
        z += GoodnessComparer(y[i])
print(z)

编辑:进行了 Cristian Ciupitu 建议的更改 请忽略缩进错误,它们可能是我复制代码时出现的。

程序是这样工作的:

获取输入并将其拆分为列表 对于每个列表值,我都会将其提供给善良的发现者。 它获取字符串的优度并将其他所有内容进行比较,当优度较高时,它会将较高的优度作为比较优度。 然后它将该文本字符串移动 i 量,以查看优度是更高还是更低

我不太清楚问题出在哪里,第一次测试:LQKP OG CV GKIJV DA VJG BQQ 打印正确的消息:在动物园旁加入我

但是下一个测试:UIJT JT B TBNQMF MJOF PG UFYU GPS EFDSZQUJOH 给出一个垃圾字符串:SGHR HR Z RZLOKD KHMD NE SDWS ENQ CDBQXOSHMF 当它应该是:这是一个用于解密的示例文本行

我知道我必须: 尝试每个班次值 得到这个词的“善良” 返回优度最高的字符串。

我希望我的解释是有道理的,因为我现在很困惑。

【问题讨论】:

如果你给垃圾字符串'SGHR HR Z RZLOKD ...'中的每个字符加1,你会得到'THIS IS A SAMPLE ...',所以它几乎是正确的。 您应该尝试用有意义的常量替换一些神奇的数字,例如65 与ord('A'),26 与NUM_LETTERS。顺便说一句,在GoodnessComparer 你有range(0, 25) 而不是(0, 26);这是一个错字吗?还有一件事:在GoodnessFinder 中,你不需要每次都做ord(i),只有当i 是一个空格时(' ')。 input() 等同于 eval(raw_input()) 没有意义,所以用普通的 raw_input() 调用替换它。 @Cristian Ciupitu:那应该是 Python 3 代码。 由于 Stack Overflow 允许您发布自己问题的答案并且这是一项家庭作业,因此您应该发布解码器的最终版本。 【参考方案1】:

这是我的实现,效果很好。

您应该打印每条可能消息的优点,并查看程序输出它的原因。

letterGoodness = dict(zip(string.ascii_uppercase,
                        [.0817,.0149,.0278,.0425,.1270,.0223,.0202,
                         .0609,.0697,.0015,.0077,.0402,.0241,.0675,
                         .0751,.0193,.0009,.0599,.0633,.0906,.0276,
                         .0098,.0236,.0015,.0197,.0007]))

trans_tables = [ str.maketrans(string.ascii_uppercase,
                 string.ascii_uppercase[i:]+string.ascii_uppercase[:i])
                 for i in range(26)]

def goodness(msg):
    return sum(letterGoodness.get(char, 0) for char in msg)

def all_shifts(msg):
    msg = msg.upper()
    for trans_table in trans_tables:
        txt = msg.translate(trans_table)
        yield goodness(txt), txt

print(max(all_shifts(input())))

【讨论】:

您已经注意到了 homework 标签,对吧?你的回答太好了。 @CristianCiupitu:所以他不能只是提交,而是先学习。【参考方案2】:

感谢出色的 Cristian Ciupitu,我的最终解决方案奏效了。

x = input()
NUM_LETTERS = 26 #Can't import modules I'm using a web based grader/compiler
def SpyCoder(S, N):
   y = ""
   for i in S:
      if(i.isupper()):
         x = ord(i)
         x += N
         if x > ord('Z'):
            x -= NUM_LETTERS
         elif x < ord('A'):
            x += NUM_LETTERS
         y += chr(x)
      else:
         y += " "
   return y

def GoodnessFinder(S):
   y = 0
   for i in S:
      if i.isupper():
         x = ord(i)
         x -= ord('A')
         y += letterGoodness[x]
      else:
         y += 1
   return y

def GoodnessComparer(S):
   goodnesstocompare = GoodnessFinder(S)
   goodness = 0
   v = ''
   best_v = S
   for i in range(0, 26):
     v = SpyCoder(S, i)
     goodness = GoodnessFinder(v)
     if goodness > goodnesstocompare:
         best_v = v
         goodnesstocompare = goodness
   return best_v


print(GoodnessComparer(x))

感谢您的所有帮助!

【讨论】:

【参考方案3】:

我正在编写相同的教程并使用了稍微不同的方法。这避免了创建和调用函数:

inp = input()     #to hold code text
code = list(inp)  #store code as a list
soln = []         #store the 'Goodness' for each of 26 possible answers
y=0               #variable to hold total goodness during calculations
clear = []        #will hold decoded text
pos=0             #position marker for a list

#for every possible value of shift
#note range as 0 to 25 are valid shifts and shift 26 = shift 0

for shift in range(0,26):
   for i in code:                  #loop through each letter in code
      if i == " ":                 #spaces have no score so omit them
         continue
      else:                        #if it's a letter
         x = ord(i)-shift          #apply the test shift
         if x < 65:                #prevent shifting outside A-Z range
            x = x + 26             
         x = x - 64                #turn ord into character position in A-Z with A=1
         x = letterGoodness[x-1]   #turn this into the Goodness score
         y = y + x                 #add this to a running total
   soln.insert(shift-1,y)          #AFTER decoding all letters in code, add total(y) to list of scores
   y = 0                           #reset y before next test value

bestSoln=max(soln)                 #find highest possible score

for i in range(0,26):              #check the list of solutions for this score
   if soln[i]==bestSoln:           #the position in this list is the shift we need
       bestShift = i+1             #+1 as the first solution is 0

for i in code:                     #now decode the original text using our best solution
   if i == " ":                    #spaces are not encoded so just add these to the string
      clear.insert(pos," ")        #pos used to track next position for final string
      pos = pos + 1
      continue
   else:
      x = ord(i)-bestShift         #same operation as before
      if x < 65:
         x = x + 26
   z = chr(x)
   clear.insert(pos,z)             #add the decoded letter to the clear text
   pos = pos + 1
print("".join(clear))              #join the list of clear text into one string and print it

请注意,此代码的许多部分可以(并且应该)被压缩,例如

x = x - 64
x = letterGoodness[x-1]
y = y + x

它们被扩展为“展示我的工作”以进行教程练习。

【讨论】:

以上是关于Python 凯撒密码解码器的主要内容,如果未能解决你的问题,请参考以下文章

python-凯撒密码加解密

基于python实现暴力破解凯撒密码

Python凯撒密码和反密码

jmu-python-凯撒密码加密算法,谢谢

加密给定的文本字符串 - 凯撒密码 [关闭]

Python 凯撒密码脚本