2015-01-21 109 views
0

因此,我一直試圖使用python實現無限猴定理。問題陳述就像這樣。嘗試使用Python的無限猴定理使用Python

這個定理指出,一隻猴子在打字機鍵盤上隨意敲擊鍵無限次地將鍵入給定的文本,如威廉莎士比亞的完整作品。那麼,假設我們用一個Python函數替換一隻猴子。這句話是:「認爲它就像一個狡猾的人」

我們將模擬這個的方法是編寫一個函數,通過從字母表中的26個字母中選擇隨機字母加上空間。我們將編寫另一個函數,通過比較隨機生成的字符串和目標來對每個生成的字符串進行評分。

第三個函數會重複調用generate和score,那麼如果100%的字母都是正確的,我們就完成了。如果這些字母不正確,我們將生成一個全新的字符串。

import random,string 

shakespeare = 'methinks it is a weasel' 

def generate(): 
char = string.ascii_lowercase+' ' 
randchars = ''.join(random.choice(char) for _ in range(27)) 
return randchars 

def score(): 
scorenum = 0 
randchars = generate() 
print randchars 
shake = shakespeare.split() 
randlist = randchars.split() 
for i,j in zip(shake,randlist): 
    if i==j: 
    scorenum = scorenum+1 
    scorecount = (scorenum/27)*100 
return scorecount 

def main(): 
run = 0 
while not(score()==100): 
    score() 
    run = run + 1 
    print run 
    if run ==1000: 
    print score() 

if __name__ == '__main__': 
main() 

因此,該程序運行的罰款,但我可以看到出現兩次,當我打印出來的隨機字符串,我已經達到3000000馬克沒有達到在匹配方面的任何成功。我相信我錯誤地寫了主要功能,但我還不確定這個問題。

如果你能幫我解決這個問題,請提前致謝。 :)

+0

請忽略的打印語句,已經把它們進行調試。 – 2015-01-21 07:31:03

+0

我把這個問題給了一隻猴子。他沒有留下深刻的印象。說莎士比亞粗魯的東西.... – 2015-01-21 07:33:28

+2

在23個字符長的字符串。所以你有23^26 = 2.5405265e + 35選項。 3百萬不算什麼。實質上,你所要做的就是通過蠻力攻擊密碼。這將需要時間。 – RedX 2015-01-21 07:33:30

回答

2

每次呼叫分數()的時候,你會產生一種新的說法,這意味着在這個循環中......

while not(score()==100): 
    score() 
    run = run + 1 
    print run 
    if run ==1000: 
     print score() 

...你生成的聲明至少兩次,有時三次。

你可能喜歡的東西替代它:

while not(score()==100): 
    run = run + 1 
    print run 

潛在組合的數量是巨大的 - 你能足夠長的時間看到任何接近可讀的句子運行這個的機會,沒關係一個匹配你正在尋找的確切句子,真的很遙遠!

下面是產生匹配的例子(我已經看到在3字符引用幾個33%匹配):

import random,string 

# shakespeare = 'methinks it is a weasel' 
shakespeare = 'abc' 
quoteLen = len(shakespeare) 

def generate(): 
char = string.ascii_lowercase+' ' 
randchars = ''.join(random.choice(char) for _ in range(quoteLen)) 
return randchars 

def score(): 
scorenum = 0 
randchars = generate() 
shake = shakespeare.split() 
randlist = randchars.split() 
for i,j in zip(shake,randlist): 
    if i==j: 
    scorenum = scorenum+1 
scorecount = (scorenum/quoteLen) * 100 
return scorecount 

def main(): 
run = 0 
curScore = 0 
while not(curScore==100): 
    curScore = score() 
    if (curScore != 0):  
    print(run, " = ", curScore) 
    run = run + 1; 

if __name__ == '__main__': 
main() 

輸出示例:

2246 = 33.33333333333333 
56731 = 33.33333333333333 
83249 = 33.33333333333333 
88370 = 33.33333333333333 
92611 = 33.33333333333333 
97535 = 33.33333333333333 
+1

這是有用的!沒有注意到雙重分數()電話..謝謝你:) – 2015-01-21 07:49:27

+0

我減少了3個字符的樣本大小,並刪除了分數(),仍然不起作用:( – 2015-01-21 08:16:40

+0

我已經添加了一個我剛剛運行的示例並且看到幾個33%的匹配(在一個3字符的引用上),我將分數寫到一個變量中,並且我也將'scorecount'的計算拉回了一個級別,以便在for循環結束後只計算一次。 – Alan 2015-01-21 09:54:00

0

即使它是均勻分佈,則得分100的機率是1/27^27(字母餌+空間中的字母數)。 3百萬退休是一個非常小的數字......

如果你想檢查你的代碼是否可以在較小的樣本上運行,比如:2-4個字符。

+0

我在上面,謝謝! – 2015-01-21 07:53:12

0

優化版本,存儲匹配的歷史記錄。爲了100%匹配,需要在480到820次迭代之間進行任何操作。

import random 

def generate(length): 

    monkey_types = "" 

    for x in range(length): 
     monkey_types = monkey_types + random.choice('abcdefghijklmnopqrstuvwxyz ') 

    return monkey_types 

def score_me(monkey_pwd, pwd): 

    score = 0 

    if len(pwd) == 1: 
     return (monkey_pwd[:1] == pwd[:1]) 

    for x in range(1,len(pwd)): 
     if monkey_pwd[:x] == pwd[:x]: 
      score = score + 1 
    return (score) 

def main(): 

    pwd = 'methinks it is like a weasel' 
    score = best_score = count = 0 
    best_guess = "" 

    while(best_score < len(pwd)): 
     iter = generate(len(pwd)-best_score) 
     score = score_me(iter, pwd[best_score:]) 
     if score > 0: 
      best_score += score 
      best_guess += iter[:score] 

     count = count+1 
     print(best_guess) 

    print("Total runs: ", count) 

if __name__ == "__main__": 

    main() 
0

以下使用(軟)Python線程模擬多個猴子。

猴子的「打字機」只包含目標莎士比亞文本(例如t,o,b,e,r,space)中存在的字母,所以它實際上解決了一個比猴子隨機打字小得多的問題在一臺完整的打字機上。即便如此,猴子仍然努力連續輸入3個以上的短文。

import threading 
import time 
from random import choice 
shakespeare = 'to be or' 
max_length = max(50, len(shakespeare)) 
alphabet = list(set(shakespeare)) 
no_of_monkeys = 4 


class Monkey(threading.Thread): 
    def __init__(self, monkey_id): 
     threading.Thread.__init__(self) 
     self.writings = '' 
     self.writings_length = 0 
     self.monkey_id = monkey_id 

    def run(self): 
     while not shakespeare in self.writings: 
      len_writings = len(self.writings) 
      if len(self.writings) > max_length: 
       self.writings = self.writings[:-max_length] 
      self.writings += choice(alphabet) 
      self.writings_length += 1 


def ellipsis_quote(s, surround_size=20): 
    shakespeare_at = s.index(shakespeare) 
    start = max(0, shakespeare_at - surround_size) 
    finish = min(shakespeare_at + surround_size, len(s)) 
    return '...' + s[start:finish] + '...' 


monkeys = [Monkey(monkey_id) for monkey_id, monkey in enumerate(range(no_of_monkeys))] 
[monkey.start() for monkey in monkeys] 
monkey_literature = False 
while not monkey_literature: 
    print "Scanning..." 
    for monkey_id, monkey in enumerate(monkeys): 
     if shakespeare in monkey.writings: 
      print '' 
      print "Monkey {monkey_id} wrote Shakespeare!".format(monkey_id=monkey_id) 
      pronoun = choice(['he', 'she']) 
      print "Here's what {pronoun} wrote:".format(pronoun=pronoun) 
      print ellipsis_quote(monkey.writings) 
      print 'after typing {length} letters'.format(length=monkey.writings_length) 
      monkey_literature = True 
    time.sleep(2) 

結果舉例:

/usr/bin/python2.7 /home/vagrant/code/monkeys/monkeys.py 
Scanning... 

Monkey 0 wrote Shakespeare! 
Here's what she wrote: 
... bbrtbr rto be or... 
after typing 1031167 letters