乌龟在多次移动后崩溃

huangapple go评论64阅读模式
英文:

Turtle crashing after many moves

问题

I'm messing around with recursion and decided to turtle. I'm trying to get some code to build a Sierpinski Triangle and it's working pretty well so far! However, when I plug in larger values of n to my function to get more detailed triangles, it just crashes after exactly 990 turtle moves. Here's the error it gives me:

File "C:\Users\[censored]\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 106, in _cnfmerge
      elif isinstance(cnfs, (type(None), str)):
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  RecursionError: maximum recursion depth exceeded in __instancecheck__

The way my code works is that it has an initial algorithm that generates a string of characters that code to different things the turtle should do. Here is the algorithm:

def sierpinski(n: int) -> str:
      if n==0:
          return 'fll'*3
      sierpenski_smaller=sierpenski(n-1)
      side_length_of_smaller=2**(n-1)
      thing_to_return=sierpenski_smaller
      thing_to_return+='f'*side_length_of_smaller
      thing_to_return+=sierpenski_smaller
      thing_to_return+='l'
      thing_to_return+='f'*side_length_of_smaller
      thing_to_return+='ll'
      thing_to_return+=sierpenski_smaller.replace('l',' ').replace('r','l').replace(' ','r')
      thing_to_return+='f'*side_length_of_smaller
      thing_to_return+='l'
      thing_to_return+='f'*side_length_of_smaller
      thing_to_return+='ll'
      return thing_to_return

After generating this string, my code passes it into a function that recursively runs the commands. Here is the code:

def execute(commands: str) -> None:
      if commands=='':
          return
      if commands[0]=='f':
          t.fd(20)
      if commands[0]=='l':
          t.lt(60)
      if commands[0]=='r':
          t.rt(60)
      execute(commands[1:])
英文:

I'm messing around with recursion and decided to turtle. I'm trying to get some code to build a Sierpenski Triangle and it's working pretty well so far! However, when I plug in larger values of n to my function to get more detailed triangles, it just crashes after exactly 990 turtle moves. Here's the error it gives me:

File "C:\Users\[censored]\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 106, in _cnfmerge
      elif isinstance(cnfs, (type(None), str)):
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  RecursionError: maximum recursion depth exceeded in __instancecheck__

The way my code works is that it has an initial algorithm that generates a string of characters that code to different things the turtle should do. Here is the algorithm:

def sierpenski(n: int) -> str:
      if n==0:
          return 'fll'*3
      sierpenski_smaller=sierpenski(n-1)
      side_length_of_smaller=2**(n-1)
      thing_to_return=sierpenski_smaller
      thing_to_return+='f'*side_length_of_smaller
      thing_to_return+=sierpenski_smaller
      thing_to_return+='l'
      thing_to_return+='f'*side_length_of_smaller
      thing_to_return+='ll'
      thing_to_return+=sierpenski_smaller.replace('l',' ').replace('r','l').replace(' ','r')
      thing_to_return+='f'*side_length_of_smaller
      thing_to_return+='l'
      thing_to_return+='f'*side_length_of_smaller
      thing_to_return+='ll'
      return thing_to_return

After generating this string, my code passes it into a function that recursively runs the commands. Here is the code:

def execute(commands: str) -> None:
      if commands=='':
          return
      if commands[0]=='f':
          t.fd(20)
      if commands[0]=='l':
          t.lt(60)
      if commands[0]=='r':
          t.rt(60)
      execute(commands[1:]) 

答案1

得分: 1

有一些递归算法适合使用递归函数,比如你的sierpenski()函数,用于计算递归分形。但对于你的execute()函数,这并不适用,因为它处理的是非递归的字符线性列表(str)。

Python有一个递归深度限制,用于查找无限递归的代码。你可以使用sys.getrecursionlimit()来查询这个限制,还可以使用sys.setrecursionlimit()来增加或减少这个限制。但是,这并不是你的问题的解决方法。

当你运行sierpenski(10)时,它能正常工作,因为它的递归深度为10,远低于默认限制1000。然而,它生成的字符串有接近一百万个字符(940,685个)。你无法将递归深度延伸到那么远。你需要按照@Stef在他们的评论中建议的,将这个字符串的非递归解释写成非递归函数(+1):

def execute(commands: str) -> None:
    for command in commands:
        if command == 'f':
            t.forward(20)
        elif command == 'l':
            t.left(60)
        elif command == 'r':
            t.right(60)

现在你的递归限制只适用于sierpenski()函数本身,它可以达到sierpenski(900),但我猜没有人有时间等待它完成!

英文:

There are recursive algorithms for which a recursion function is reasonable, like your sierpenski() function which computes a recursive fractal. But this isn't true of your execute() function which processes a non-recursive, linear list of characters (str).

Python has a set recursion limit to look for runaway code. You can interrogate this limit using sys.getrecursionlimit() and you can increase, or decrease, this limit with sys.setrecursionlimit(). But, this isn't the fix for you.

When you run sierpenski(10), it works fine as it recurses 10 levels which is well below the default limit of 1000. However, the string it produces has just shy of one million characters (940,685). You can't hope to stretch the recursion limit that far. You need to write the non-recursive interpretation of this string as a non-recursive function as @Stef suggests in their comment (+1):

def execute(commands: str) -> None:
	for command in commands:
		if command == 'f':
			t.forward(20)
		elif command == 'l':
			t.left(60)
		elif command == 'r':
			t.right(60)

Now your recursive limitation is on the sierpenski() function alone, which can approach sierpenski(900), but my guess is no one has time to wait for that to complete!

huangapple
  • 本文由 发表于 2023年6月15日 11:43:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76478953.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定