2009-10-28 113 views
0

我目前正試圖深入挖掘python,並且我發現了一個對(hackthissite.org)的挑戰,我試圖破解它。我必須解讀在提供的單詞表中找到的10個單詞。解密Python字解密器

def permutation(s): 
    if s == "": 
     return [s] 
    else: 
     ans = [] 
     for an in permutation(s[1:]): 
      for pos in range(len(an)+1): 
       ans.append(an[:pos]+s[0]+an[pos:]) 
     return ans 

def dictionary(wordlist): 
    dict = {} 
    infile = open(wordlist, "r") 
    for line in infile: 
     word = line.split("\n")[0] 
     # all words in lower case!!! 
     word = word.lower() 
     dict[word] = 1 
    infile.close() 
    return dict 

def main(): 
    diction = dictionary("wordlist.txt") 
    # enter all the words that fit on a line or limit the number 
    anagram = raw_input("Please enter space separated words you need to unscramble: ") 
    wordLst = anagram.split(None) 

    for word in wordLst: 
     anaLst = permutation(word) 
     for ana in anaLst: 
      if diction.has_key(ana): 
       diction[ana] = word 
       #print "The solution to the jumble is" , ana 
    solutionLst = [] 
    for k, v in diction.iteritems(): 
     if v != 1: 
      solutionLst.append(k) 
      print "%s unscrambled = %s" % (v, k) 
    print solutionLst 

main() 

功能排列看起來像是實際解密的代碼塊。你能幫我理解它在編程上如何解決這個問題嗎?

+0

您的縮進被打破。 – SilentGhost 2009-10-28 15:23:12

+0

是的,要正確地粘貼python是很困難的。 – adam 2009-10-28 15:25:28

+0

如果您將'permutation'函數識別爲正在執行實際工作的函數,您不能單獨運行它並查看它返回的結果嗎? – SilentGhost 2009-10-28 15:28:34

回答

3

造成這種情況的僞代碼如下所示:

Load the word list (dictionary) 
Input the words to unscramble 
For each word: 
    Find every permutation of letters in that word (permutation) 
    For each permutation: 
    Add this permutation to the solution list if it exists in the dictionary 
Print the solutions that were found. 

字典()函數從一個文件填充你的單詞列表。

permutation()函數返回給定單詞中每個字母的排列。


置換()函數執行以下操作:

for an in permutation(s[1:]): 

S [1:]返回與截斷的第一個字符的字符串。你會看到它使用遞歸來再次調用permutation(),直到沒有字符從前面被截斷爲止。你必須知道遞歸來理解這一行。使用遞歸允許這個算法覆蓋每一個字母,並且仍然很優雅。

for pos in range(len(an)+1): 

對於每個剩餘的字母位置。

ans.append(an[:pos]+s[0]+an[pos:]) 

通過移動的第一個字母(我們前面截斷)每個其他字母之間的位置生成置換。


因此,以「手錶」爲例。遞歸後,會有產生下面的話一個循環:

awtch atwch atcwh atchw

我所做的一切來生成這些字眼取第一個字母,並改變其位置。繼續,結合截斷字母,你會創造每一個排列。

(哇,這必須是我最長的答案了)

+0

謝謝......現在我的程序對我來說有點清晰了。 – adam 2009-10-28 15:38:41

+0

我添加了一個更詳細解釋permutation()函數的更新。我希望更清楚:D – Kai 2009-10-28 15:41:23

+0

非常感謝你,你對我的理解有了很大的幫助。再次感謝 – adam 2009-10-28 15:49:51

0

有一個更好的解決方案。如果有很多長詞,此代碼效率非常低。一個更好的想法是按字典順序排列字典中的每個單詞,這樣'上帝'變成'dgo',並且對於亂碼的單詞也是這樣。然後它是O(nlogn)爲每個單詞而不是O(n!)

0

我也爲該網站編寫了此代碼。下面 工作代碼:

def import_dictionary(): 
    dictionary = [] 
    try: 
     file = open("C:\\Users\\Mason\\Desktop\\diction.txt", "r")#location of your dictionary or provided wordlist 
     fileContents = file.readlines() #read text file and store each new line as a string 
    finally: 
     file.close() 
    for i in range(len(fileContents)): 
     dictionary.extend(fileContents[i].split()) #changes the list by removing \n's from line breaks in text file 
    return dictionary 

def import_scrambled_words(): 
    scrambledWords = [] 
    try: 
     file = open("C:\\Users\\Mason\\Desktop\\scrambled.txt", "r") #location of your scrambled word file 
     fileContents = file.readlines() #read text file and store each new line as a string 
    finally: 
     file.close() 
    for i in range(len(fileContents)): 
     scrambledWords.extend(fileContents[i].split()) #changes the list by removing \n's from line breaks in text file 
    return scrambledWords 

def unscramble_word(scrambledWord): 
    countToMatch = len(scrambledWord) 
    matchedWords = [] 
    string = "" 

    for word in dictionary: 
     count = 0 
     for x in scrambledWord: 
      if x in word: 
       count += 1 
      if count == countToMatch: 
       matchedWords.append(word) 
       break 
    for matchedWord in matchedWords: 
     if len(matchedWord) == len(scrambledWord): 
      print(matchedWord) 
      string = matchedWord 
      break #this returns only one unscrambles word 
    return string 

if __name__ == '__main__': 
    finalString = "" 
    try: 
     scrambled = import_scrambled_words() 
     print(scrambled) 
     dictionary = import_dictionary() 
     for x in scrambled: 
      finalString += unscramble_word(x) 
      finalString +=", " 
     len(finalString) 

     print(finalString) 

    except Exception as e: 
     print(e) 

此代碼將從炒字保存的文件讀取,並檢查它針對的詞表(我使用的字典在我的情況只是要另計)。爲了在分配的30秒內擊敗挑戰,我從hackThissite複製粘貼並粘貼到我的炒字文件。保存。運行程序並複製粘貼我的python控制檯的輸出。