使用Python尝试无限猴子定理

时间:2015-01-21 07:28:26

标签: python string

所以,我一直试图用python实现无限猴子定理。问题陈述是这样的。

该定理指出,猴子在打字机键盘上随机敲击键无限时间几乎肯定会键入给定的文本,例如威廉·莎士比亚的全集。好吧,假设我们用Python函数替换猴子。这句话是:“认为它就像一个黄鼠狼”

我们模拟这个的方法是编写一个函数,通过从字母表中的26个字母加空格中选择随机字母来生成长度为27个字符的字符串。我们将编写另一个函数,通过将随机生成的字符串与目标进行比较,对每个生成的字符串进行评分。

第三个函数将重复调用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()

所以,该程序运行正常,但我可以看到随机字符串在我打印时出现两次,而且我已达到300万分,但在匹配方面没有取得任何成功。我相信我已经错误地写了主要功能,但我还不确定问题。

如果你能帮助我解决这个问题,请提前致谢。 :)

7 个答案:

答案 0 :(得分:2)

每次调用score()时,您都会生成一个新语句,这意味着在此循环中......

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 :(得分:1)

即使它的分布均匀,得分100的几率为1/27 ^ 27(alpha-bait +空格中的字母数)。 300万退休是一个非常小的数字...

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

答案 2 :(得分:1)

优化版本,存储匹配的历史记录。需要480到820次迭代才能达到100%匹配。

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()

答案 3 :(得分:1)

以下使用(软)Python线程模拟多个猴子。

猴子的“打字机”只包含目标莎士比亚文本中存在的字母(例如t,o,b,e,r,空格),所以它实际上解决的问题要小于随机打字的猴子。一台完整的打字机。即便如此,猴子仍然难以连续输入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

答案 4 :(得分:1)

更多优化版本:),完成匹配需要不到100次迭代。我认为这会有所帮助。

import string
import random

def randomGen(goalList):
    characters = string.ascii_lowercase+" "
    randString =""
    for i in range(len(goalList)):
        randString = randString+characters[random.randrange(len(characters))]
    randList = [randString[i] for i in range(len(randString))]
    return randList

def scoreRand(goalList,randList):
    numScore = 0
    for i in range(len(goalList)):
        if goalList[i] == randList[i]:
            numScore = numScore+1
    return numScore / len(goalList)

def common_elements(clist,list1, list2):
    for i in range(len(list1)):
        if list1[i] == list2[i]:
            clist[i] = list1[i]
    return clist

def main():
    goal = "methinks it is like a weasel"
    goalList = [goal[i] for i in range(len(goal))]
    clist = [' ' for i in range(len(goal))]
    randList = randomGen(goalList)
    clist = common_elements(clist,goalList, randList)
    score = scoreRand(goalList,clist)
    totalIteration = 0
    while(score < 1):
        newrandList = randomGen(goalList)
        newclist = common_elements(clist,goalList, randList)
        newscore = scoreRand(goalList,clist)
        score = newscore
        randList = newrandList
        clist = newclist
        totalIteration = totalIteration+1
        print(score," : ",''.join(clist))
    print("Total iterations: ",totalIteration)

main()

答案 5 :(得分:1)

我的解决方案:

router.post('/save', (req, res)=>{
    var rdaColor = new rdaColor(
        {
            movementBox: req.body.colorMovementBox,
        }
    );
    rdaColor.save((err,doc)=> {
    if(!err){
        res.send(doc);}
        else{
            console.log(err);
        }
        });
});

答案 6 :(得分:0)

我的版本简短

from random import choice

alphabets = [chr(i) for i in range(97, 123)]
alphabets.append(" ")
string = "methinks it is like a weasel"


def random_string():
    result = ""
    i = 0
    while i < len(string):
        result += choice(alphabets)
        i += 1
    return result


def score_n_match():
    score = 0
    i = 0
    match = ""
    while i < len(string):
        temp = random_string()
        if string[i] == temp[i]:
            print(f"{i + 1} match found.")
            match += temp[i]
            i += 1
        score += 1
    print(f"generated string: {match} after {score} loops")


score_n_match()