2015-10-04 59 views
3

解碼器(S)將被賦予一串英文文本,並被移動一定的數量。然後,解碼器應該儘可能地返回原始的英文字符串,這將是輸入S的一些旋轉(可能爲0)。這意味着我必須嘗試每種可能的解碼並估計它們的英文程度。解碼python

我的做法是用字母頻率:

def letProb(c): 
    """ if c is an alphabetic character, 
    we return its monogram probability (for english), 
    otherwise we return 1.0 We ignore capitalization. 
    Adapted from 
    http://www.math.cornell.edu/~mec/2003-2004/cryptography/subs/frequencies.html 
    """ 
    if c == 'e' or c == 'E': return 0.1202 
    if c == 't' or c == 'T': return 0.0910 
    if c == 'a' or c == 'A': return 0.0812 
    if c == 'o' or c == 'O': return 0.0768 
    if c == 'i' or c == 'I': return 0.0731 
    if c == 'n' or c == 'N': return 0.0695 
    if c == 's' or c == 'S': return 0.0628 
    if c == 'r' or c == 'R': return 0.0602 
    if c == 'h' or c == 'H': return 0.0592 
    if c == 'd' or c == 'D': return 0.0432 
    if c == 'l' or c == 'L': return 0.0398 
    if c == 'u' or c == 'U': return 0.0288 
    if c == 'c' or c == 'C': return 0.0271 
    if c == 'm' or c == 'M': return 0.0261 
    if c == 'f' or c == 'F': return 0.0230 
    if c == 'y' or c == 'Y': return 0.0211 
    if c == 'w' or c == 'W': return 0.0209 
    if c == 'g' or c == 'G': return 0.0203 
    if c == 'p' or c == 'P': return 0.0182 
    if c == 'b' or c == 'B': return 0.0149 
    if c == 'v' or c == 'V': return 0.0111 
    if c == 'k' or c == 'K': return 0.0069 
    if c == 'x' or c == 'X': return 0.0017 
    if c == 'q' or c == 'Q': return 0.0011 
    if c == 'j' or c == 'J': return 0.0010 
    if c == 'z' or c == 'Z': return 0.0007 
    return 1.0 

而且我用這個公式:

def list_to_str(L): 
    """ L must be a list of characters; then, 
    this returns a single string from them 
    """ 
    if len(L) == 0: return '' 
    return L[0] + list_to_str(L[1:]) 

而且這樣的:

def rot(c, n): 
    """ rot rotates c, a single character forward by n spots in the 
     alphabet 
     input: a single character 
     input: a non-negative integer n between 0 and 25 
     output: c forward by n spots in the alphabet 
    """ 
    if 'a' <= c <= 'z': 
     neword = ord(c) +n 
     if neword > ord('z'): 
       neword = neword - 26 
    elif 'A' <= c <= 'Z': 
     neword = ord(c) + n 
      if neword > ord('Z'): 
       neword = neword - 26 
    else:      
     neword = ord(c) 
    return chr(neword) 

最後這一點:

def decipher(S): 
    """ 
    """ 
    L = [[rot(c, n) for c in S] for n in range(26)] 
    LoL = [[sum(letProb(c)) for letter in encoding] for encoding in L ] 
    L = max(LoL) 
    return list_to_str(L) 

前兩個公式是好的,但最終配方中有什麼不對的,這是肯定的一句話:

LoL = [[sum(letProb(c)) for letter in encoding] for encoding in L ] 

類型錯誤:「浮動」對象不是可迭代

+1

使用表查找您的概率,並使用'lower'來摺疊案例。 – stark

+0

在'[[sum(letProb(c))for encoding in L]'中,變量'c'永遠不會被分配一個值,所以它的最後一行始終是' S'。 – msw

回答

1

您正在嘗試sum(letProb(c))其中letProb返回一個Float,並且總和需要一個迭代器,一個列表或一個生成器,可以說。嘗試這樣的事情。

LoL = [[sum(letProb(c) for letter in encoding)] for encoding in L ] 

我也認爲Ç也許應該是,但我不這樣做,如果你發佈完整的代碼,包括功能,也許我可以幫你更好的。

0

您可能會發現以下內容有用。你可以使用某種查找字母概率。如果使用字典,則可以使用get爲非A到Z字符提供默認概率1.0

其次,Python的string模塊有一個make_trans函數可以用於translate執行您的旋轉。

import string 

letter_probs = { 
    'e' : 0.1202, 't' : 0.0910, 'a' : 0.0812, 'o' : 0.0768, 
    'i' : 0.0731, 'n' : 0.0695, 's' : 0.0628, 'r' : 0.0602, 
    'h' : 0.0592, 'd' : 0.0432, 'l' : 0.0398, 'u' : 0.0288, 
    'c' : 0.0271, 'm' : 0.0261, 'f' : 0.0230, 'y' : 0.0211, 
    'w' : 0.0209, 'g' : 0.0203, 'p' : 0.0182, 'b' : 0.0149, 
    'v' : 0.0111, 'k' : 0.0069, 'x' : 0.0017, 'q' : 0.0011, 
    'j' : 0.0010, 'z' : 0.0007} 

def rotate(text, rotate_by): 
    s_from = string.ascii_lowercase + string.ascii_uppercase 
    s_to = string.ascii_lowercase[rotate_by:] + string.ascii_lowercase[:rotate_by] + \ 
      string.ascii_uppercase[rotate_by:] + string.ascii_uppercase[:rotate_by] 
    cypher_table = string.maketrans(s_from, s_to) 
    return text.translate(cypher_table) 

def sum_probs(text): 
    global letter_probs 
    return sum(letter_probs.get(c.lower(), 1.0) for c in text) 

def decipher(text): 
    probabilities = [] 
    for r in range(26): 
     rotated = rotate(text, r) 
     probabilities.append((sum_probs(rotated), rotated, r)) 
    return sorted(probabilities) 

for probability, decoded_text, rotate_value in decipher("Mjqqt Btwqi"): 
    print '{:2.2f} {:2} "{}"'.format(probability, rotate_value, decoded_text) 

這將在概率順序顯示所有的可能性:

1.17 19 "Fcjjm Umpjb" 
1.20 16 "Czggj Rjmgy" 
1.22 9 "Vszzc Kcfzr" 
1.26 20 "Gdkkn Vnqkc" 
1.28 13 "Zwddg Ogjdv" 
1.29 4 "Qnuux Fxaum" 
1.29 15 "Byffi Qilfx" 
1.30 8 "Uryyb Jbeyq" 
1.31 6 "Spwwz Hzcwo" 
1.32 5 "Rovvy Gybvn" 
1.32 0 "Mjqqt Btwqi" 
1.33 12 "Yvccf Nficu" 
1.34 1 "Nkrru Cuxrj" 
1.37 23 "Jgnnq Yqtnf" 
1.39 7 "Tqxxa Iadxp" 
1.40 22 "Ifmmp Xpsme" 
1.40 2 "Olssv Dvysk" 
1.44 25 "Lipps Asvph" 
1.45 17 "Dahhk Sknhz" 
1.47 24 "Khoor Zruog" 
1.49 11 "Xubbe Mehbt" 
1.52 3 "Pmttw Ewztl" 
1.56 10 "Wtaad Ldgas" 
1.58 21 "Hello World" 
1.61 14 "Axeeh Phkew" 
1.68 18 "Ebiil Tloia" 

正如你所看到的,答案是接近底部。