【问题标题】:Recursion errors in a dice rolling simluation (how long to match 'x' dice in one roll)掷骰子模拟中的递归错误(在一次掷骰中匹配“x”骰子需要多长时间)
【发布时间】:2015-12-16 21:25:43
【问题描述】:

好的,对编码和 python 来说非常非常新。

此脚本的目标:您必须掷多少次“x”骰子才能使它们都得到相同的值?

这是它试图做的事情: 从用户那里拿一些骰子 模拟掷骰子 如果所有骰子都匹配,则打印尝试成功的次数,如果不匹配,请重试。

会发生什么:

如果用户输入少量骰子,1-4 左右,它可以正常工作。

一旦用户输入 5 个(或更多)骰子,就会遇到“调用 python 对象时超出最大递归深度”错误。它似乎是调用 random.randint 的一部分

鉴于我不确定为什么递归变得无限,我希望有人能给我一些关于如何避免此错误的指导。我试图评论我的代码以使其有意义(至少对我而言)。

如果重要的话,我正在 Enthought Canopy 环境中使用 python 2.6。

import random

#create the empty list to store values
dierolls = []  

#used to roll ythe dice
def diceroll():  
    return random.randint(1,6)

#gets user input to determine how many dice we are rollin    
def askfornumofdicetoroll():  
    return int(input("How many dice should we roll?"))

#fills the dierolls list with the appropriate     
def fillthelist(dicecount): 
    #empty the list and start fresh each iteration
    dierolls[:] = []

    #input a die roll for each die the user says to roll
    for i in range(0,dicecount):
        dierolls.append(diceroll())
    #print dierolls #used to check that this code was running
    return dierolls

#what to do when all the dice match
def wongame(attempts):
    print("You matched all the dice in", attempts , "tries")

#compares all the items in the list, and see's if they match
def comparelist(dicetoroll,attempts):

    fillthelist(dicetoroll)
    #print statement used to make sure this was running
    print dierolls
    #print statment used to see if this section of code was running
    print(all(dierolls[0] == elem for elem in dierolls))

    #gives a check to make sure the code is running and not stopped by
    #printing a result every 100 attempts
    if attempts%100 == True:
        print attempts
    else:
        pass

    #does the actual check to see if all items in the list are the same
    if all(dierolls[0] == elem for elem in dierolls):
        #if all items in list are the same, go to the results function
        wongame(attempts)
    else:
        #increment the attempts counter, and try again
        attempts += 1
        comparelist(dicetoroll, attempts)  

#runs the program
def main():
    attempts = 1
    dicetoroll = askfornumofdicetoroll()
    comparelist(dicetoroll,attempts)

【问题讨论】:

  • 你有有限的,但在comparelist非常长递归,你不应该这样编码 - 如果你应该多次重复代码使用循环 不是递归。

标签: python python-2.7


【解决方案1】:

Python 有fairly low recursion limit by default (IIRC, 1000 stack frames)。您的代码没有限制递归(没有maximum_attempts 检查),所以如果它递归太多次试图“获胜”,它就会达到限制并死亡。

你可以set a higher recursion limit,但这只是稍微扩大了上限;每个额外的骰子都会将给定掷骰的获胜几率降低 1/6,因此您总是用一个骰子获胜,两个骰子赢得 1/6,三个骰子赢得 1/36,4 个骰子为 1/216,5 个骰子为 1/1296,等等. 获胜的几率迅速下降;更高的递归限制仍然偶尔会偶然失败,并且在大多数情况下它不会为您提供更多的额外容量。

您确实需要放弃递归,转而使用命令式技术。

【讨论】:

    【解决方案2】:

    在回答您的问题时,避免此错误的最佳方法是避免递归。尽管可以说大多数迭代过程都可以递归完成,但这并不意味着它应该是。

    在您的情况下,您正在尝试迭代不确定的次数,随着骰子数量的增加,这些次数可能会呈指数增长,因为掷骰子中的组合数量为 6^n 或 @ 987654322@ 为n 骰子数。

    不仅如此,您的迭代很简单,每次只需将单个变量 (attempts) 迭代 1。换句话说,您一遍又一遍地运行 EXACT SAME 代码……一遍又一遍,直到某个停止条件。对此的通常答案是什么?一个循环。更具体地说,一个while循环。不需要递归。

    因此将您的代码重组为:

    #compares all the items in the list, and see's if they match
    def comparelist(dicetoroll,attempts):
    
        #continue doing this unless break or return
        while True:
            fillthelist(dicetoroll)
            #print statement used to make sure this was running
            print dierolls
            #print statment used to see if this section of code was running
            print(all(dierolls[0] == elem for elem in dierolls))
    
            #gives a check to make sure the code is running and not stopped by
            #printing a result every 100 attempts
            if attempts%100 == True:
                print attempts
            else:
                pass
    
            #does the actual check to see if all items in the list are the same
            if all(dierolls[0] == elem for elem in dierolls):
                #if all items in list are the same, go to the results function
                wongame(attempts)
                #break out of the loop
                break
            else:
                #increment the attempts counter, and try again
                attempts += 1
         return #if you want the function to return something
    

    【讨论】:

    • 非常感谢!我做了while循环调整,一切都很完美!我将来会努力不使用递归。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2011-07-12
    • 2018-09-08
    • 1970-01-01
    • 1970-01-01
    • 2018-01-03
    • 2019-03-09
    • 1970-01-01
    相关资源
    最近更新 更多