尝试使用Python的无限猴定理使用Python

问题描述:

因此,我一直试图使用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

每次呼叫分数()的时候,你会产生一种新的说法,这意味着在这个循环中......

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

即使它是均匀分布,则得分100的几率是1/27^27(字母饵+空间中的字母数)。 3百万退休是一个非常小的数字......

如果你想检查你的代码是否可以在较小的样本上运行,比如:2-4个字符。

+0

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

优化版本,存储匹配的历史记录。为了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() 

以下使用(软)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