2016-11-28 44 views
1

我正在尝试使用python来帮助我破解Vigenère密码。我对编程相当陌生,但我设法制作了一个算法来分析一串文本中的二元语音频率。这是我到目前为止有:使用python分析一串文本中的bigrams

import nltk, string 
from nltk import bigrams 

Ciphertext = str(input("What is the text to be analysed?")) 

#Removes spacing and punctuation to make the text easier to analyse 
def Remove_Formatting(str): 
    str = str.upper() 
    str = str.strip() 
    str = str.replace(' ','') 
    str = str.translate(str.maketrans({a:None for a in string.punctuation})) 
    return str 

Ciphertext = Remove_Formatting(Ciphertext) 

#Score is meant to increase if most common bigrams are in the text 
def Bigram(str): 
    Common_Bigrams = ['TH',  'EN',  'NG', 
         'HE',  'AT',  'AL', 
         'IN',  'ED',  'IT', 
         'ER',  'ND',  'AS', 
         'AN',  'TO',  'IS', 
         'RE',  'OR',  'HA', 
         'ES',  'EA',  'ET', 
         'ON',  'TI',  'SE', 
         'ST',  'AR',  'OU', 
         'NT',  'TE',  'OF'] 
    Bigram_score = int(0) 
    for bigram in str: 
     if bigram in Common_Bigrams: 
      Bigram_score += 1 
      return Bigram_score 

Bigram(Ciphertext) 

print (Bigram_score) 

然而,当我试图用一个文本运行此我得到这个错误:

Traceback (most recent call last): 
    File "C:/Users/Tony/Desktop/Bigrams.py", line 36, in <module> 
    print (Bigram_score) 
NameError: name 'Bigram_score' is not defined 

这是什么意思?我以为我已经将Bigram_score定义为一个变量,并且我已经尝试了所有内容,但它仍以这种方式或那种方式返回错误。我做错了什么?请帮助...

由于提前,

托尼

回答

1

你可以做Bigram_score全球性的,就像这样:

def Bigram(string): # don't override str 
    global Bigram_score 
    Common_Bigrams = ['TH',  'EN',  'NG', 
         'HE',  'AT',  'AL', 
         'IN',  'ED',  'IT', 
         'ER',  'ND',  'AS', 
         'AN',  'TO',  'IS', 
         'RE',  'OR',  'HA', 
         'ES',  'EA',  'ET', 
         'ON',  'TI',  'SE', 
         'ST',  'AR',  'OU', 
         'NT',  'TE',  'OF'] 
    Bigram_score = 0 # that 0 is an integer is implicitly understood 
    for bigram in string: 
     if bigram in Common_Bigrams: 
      Bigram_score += 1 
      return Bigram_score 

您也返回的结果从Bigram功能绑定一个变量,如下所示:

Bigram_score = Bigram(Ciphertext) 

print(Bigram_score) 

或者:

print(Bigram(Ciphertext)) 

当您为函数中的变量赋值时,它们是本地的并绑定到该函数。如果一个函数返回任何东西,返回值必须绑定到一个变量才能正确重用(或直接使用)。

这是它如何工作的例子:

spam = "spam" # global spam variable 

def change_spam(): 
    spam = "ham" # setting the local spam variable 
    return spam 

change_spam() 
print(spam) # prints spam 

spam = change_spam() # here we assign the returned value to global spam 
print(spam) # prints ham 

另外,你的for循环遍历unigram进行,而不是二元语法。让我们仔细看看:

for x in "hellothere": 
    print(x) 

这将打印unigrams。因此,我们重命名代码中的bigram变量,以查看哪里存在一些逻辑问题。

for unigram in string: 
    if unigram in Common_Bigrams: 
     print("bigram hit!") 

由于没有对unigram是相同与任何双字母组,"bigram hit!"将永远不会被打印。我们可以尝试使用不同的方法获得bigrams,使用while循环和索引号。

index = 0 
n = 2 # for bigrams 
while index < len(string)-(n-1): # minus the length of n-1 (n-grams) 
    ngram = string[index:index+n] # collect ngram 
    index += 1 # important to add this, otherwise the loop is eternal! 
    print(ngram) 

接下来,只是在循环中包含你想要用bigram做什么。

+0

我已经尝试过'全局'功能,而且工作,谢谢! –

+0

但是,Bigram_score原来是'0',这不是我所期望的。算法有什么问题吗? –

+0

是的,我可以看到你的算法有问题。它在for循环中,你似乎在循环每个单独的字符。事实上,你看unigrams,并问他们是否等于任何bigrams。他们永远不会这样做,并给你0分。或者至少我会猜测那就是这样。 – internetional