Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用python递归实现冰雹序列或Collatz猜想的数学难题?_Python_Algorithm_Recursion - Fatal编程技术网

用python递归实现冰雹序列或Collatz猜想的数学难题?

用python递归实现冰雹序列或Collatz猜想的数学难题?,python,algorithm,recursion,Python,Algorithm,Recursion,有一个数学难题: 选择一个正整数n作为开始 如果n是偶数,则将其除以2 如果n为奇数,则将其乘以3,再加1 继续此过程,直到n为1 我想写一个递归函数,以n为参数,然后返回一个元组,其中包括进程中n的轨迹序列和序列长度。但失败了 我的代码怎么了?如何完成这项任务 def hailstone(n): """the implementation of recursive one, return a tuple that includes the hailstone sequence

有一个数学难题:

  • 选择一个正整数n作为开始
  • 如果n是偶数,则将其除以2
  • 如果n为奇数,则将其乘以3,再加1
  • 继续此过程,直到n为1
  • 我想写一个递归函数,以n为参数,然后返回一个元组,其中包括进程中n的轨迹序列和序列长度。但失败了

    我的代码怎么了?如何完成这项任务

    def hailstone(n):
        """the implementation of recursive one,
        return a tuple that includes the hailstone sequence
        starting at n, and the length of sequence.
    
        >>> a = hailstone(1)
        ([1, 4, 2, 1], 4)
        """
        if n % 2 == 0:
            n = n//2
        else:
            n = n*3 + 1
    
        if n == 1:
            return [n]
        else:
            """
            for some magic code here,
            it will return a tuple that includes the list track of n,
            and the length of sequence,
            like ([1, 4, 2, 1], 4)
            """
            return ([n for some_magic in hailstone(n)], lenght_of_seq)
    

    您可以使用累加器:

    def hailstone(n):
        """
        return a tuple that includes the hailstone sequence
        starting at n, and the length of sequence.
        1) Pick a positive integer n as start.
        2) If n is even, then divide it by 2.
        3) If n is odd, multiply it by 3, and add 1.
        4) continue this process until n is 1.
        """
    
        def hailstone_acc(n, acc):
            acc.append(n)
            if n == 1:
                return acc, len(acc)
            elif n % 2 == 0:
                return hailstone_acc(n//2, acc)
            else:
                return hailstone_acc(3*n + 1, acc)
    
        if n == 1:
            return hailstone_acc(4,[1])
        else:
            return hailstone_acc(n, [])
    
    现在,在行动中:

    (trusty)juan@localhost:~/workspace/testing/hailstone$ python -i hailstone.py 
    >>> hailstone(1)
    ([1, 4, 2, 1], 4)
    >>> hailstone(4)
    ([4, 2, 1], 3)
    >>> hailstone(23)
    ([23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1], 16)
    >>> 
    

    您可以使用累加器:

    def hailstone(n):
        """
        return a tuple that includes the hailstone sequence
        starting at n, and the length of sequence.
        1) Pick a positive integer n as start.
        2) If n is even, then divide it by 2.
        3) If n is odd, multiply it by 3, and add 1.
        4) continue this process until n is 1.
        """
    
        def hailstone_acc(n, acc):
            acc.append(n)
            if n == 1:
                return acc, len(acc)
            elif n % 2 == 0:
                return hailstone_acc(n//2, acc)
            else:
                return hailstone_acc(3*n + 1, acc)
    
        if n == 1:
            return hailstone_acc(4,[1])
        else:
            return hailstone_acc(n, [])
    
    现在,在行动中:

    (trusty)juan@localhost:~/workspace/testing/hailstone$ python -i hailstone.py 
    >>> hailstone(1)
    ([1, 4, 2, 1], 4)
    >>> hailstone(4)
    ([4, 2, 1], 3)
    >>> hailstone(23)
    ([23, 70, 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1], 16)
    >>> 
    

    首先,您需要决定是使用迭代过程还是递归过程——在Python中这无关紧要(因为Python不采用尾部调用优化),但在语言中可以。有关迭代/递归过程的更深入解释,请参阅

    在这两种情况下,通常最好从结束条件开始,然后从那里开始工作。在这种情况下,这是
    n==1

    递归过程 让我们从一个递归过程开始。在这种情况下,状态在调用链中保持,并且在到达最里面的调用(并且返回调用链)后计算结果

    好的,这就是结束条件-现在我们已经确保函数在
    n
    为1时返回。让我们继续并添加其余条件:

    def hailstone_rec(n):
        if n == 1:
            return (n,), 1
    
        if n % 2 == 0: # Even
            rest = hailstone_rec(n//2)
        else: # Odd
            rest = hailstone_rec(n*3+1)
    
        return (n,) + rest[0], rest[1] + 1
    
    n
    不是1时,我们首先递归计算序列的其余部分,然后将当前调用的值添加到该结果中。因此,如果
    n
    为2,这意味着我们将计算
    冰雹rec(2//2)
    ,它将返回
    ((1),1)
    ,然后我们添加当前值并返回结果(
    ((2,1),2)

    迭代过程 通过迭代过程,在沿着调用链进行时计算结果,在递归时将当前状态传递给下一个函数调用。这意味着结果不依赖于调用链中较高的调用,这意味着当到达末尾时,最内层的函数可以只返回结果。这在具有尾部调用优化的语言中具有重要意义,因为外部调用的状态可能会被丢弃

    使用此过程实现函数时,使用带有额外参数的内部帮助函数传递状态通常很有帮助,因此让我们定义一个面向用户的函数和一个内部帮助函数:

    # user facing function
    def hailstone_it(n):
        # Call the helper function with initial values set
        return hailstone_it_helper(n, (), 0)
    
    # internal helper function
    def hailstone_it_helper(n, seq, length):
        pass
    
    可以看出,面向用户的函数只调用内部函数,状态参数设置为初始值。让我们继续实现实际的逻辑,所有这些逻辑都将驻留在helper中。与前面的解决方案一样,让我们从结束条件(
    n==1
    )开始:

    这一次,我们从以前的调用中获取部分结果,添加当前值,然后返回该结果。现在,处理剩余的案例:

    def hailstone_it_helper(n, seq, length):
        if n == 1:
            return seq + (n,), length + 1
    
        if n % 2 == 0: # Even
            return hailstone_it_helper(n//2, seq + (n,), length + 1)
        else:
            return hailstone_it_helper(n*3+1, seq + (n,), length + 1)
    
    def hailstone_it(n):
        return hailstone_it_helper(n, (), 0)
    
    在这里递归时,我们传入序列中的下一个n(取决于当前n是偶数还是奇数),以及到目前为止的结果

    一个更具python风格的解决方案 最后,由于您通常不会在Python中编写这样的代码,因此作为奖励,让我们以一个更具Python风格的解决方案结束(即,一个根本不使用递归的解决方案):


    首先,您需要决定是使用迭代过程还是递归过程——在Python中这无关紧要(因为Python不采用尾部调用优化),但在语言中可以。有关迭代/递归过程的更深入解释,请参阅

    在这两种情况下,通常最好从结束条件开始,然后从那里开始工作。在这种情况下,这是
    n==1

    递归过程 让我们从一个递归过程开始。在这种情况下,状态在调用链中保持,并且在到达最里面的调用(并且返回调用链)后计算结果

    好的,这就是结束条件-现在我们已经确保函数在
    n
    为1时返回。让我们继续并添加其余条件:

    def hailstone_rec(n):
        if n == 1:
            return (n,), 1
    
        if n % 2 == 0: # Even
            rest = hailstone_rec(n//2)
        else: # Odd
            rest = hailstone_rec(n*3+1)
    
        return (n,) + rest[0], rest[1] + 1
    
    n
    不是1时,我们首先递归计算序列的其余部分,然后将当前调用的值添加到该结果中。因此,如果
    n
    为2,这意味着我们将计算
    冰雹rec(2//2)
    ,它将返回
    ((1),1)
    ,然后我们添加当前值并返回结果(
    ((2,1),2)

    迭代过程 通过迭代过程,在沿着调用链进行时计算结果,在递归时将当前状态传递给下一个函数调用。这意味着结果不依赖于调用链中较高的调用,这意味着当到达末尾时,最内层的函数可以只返回结果。这在具有尾部调用优化的语言中具有重要意义,因为外部调用的状态可能会被丢弃

    使用此过程实现函数时,使用带有额外参数的内部帮助函数传递状态通常很有帮助,因此让我们定义一个面向用户的函数和一个内部帮助函数:

    # user facing function
    def hailstone_it(n):
        # Call the helper function with initial values set
        return hailstone_it_helper(n, (), 0)
    
    # internal helper function
    def hailstone_it_helper(n, seq, length):
        pass
    
    可以看出,面向用户的函数只调用内部函数,状态参数设置为初始值。让我们继续实现实际的逻辑,所有这些逻辑都将驻留在helper中。与前面的解决方案一样,让我们从结束条件(
    n==1
    )开始:

    这一次,我们从以前的调用中获取部分结果,添加当前值,然后返回该结果。现在,处理剩余的案例:

    def hailstone_it_helper(n, seq, length):
        if n == 1:
            return seq + (n,), length + 1
    
        if n % 2 == 0: # Even
            return hailstone_it_helper(n//2, seq + (n,), length + 1)
        else:
            return hailstone_it_helper(n*3+1, seq + (n,), length + 1)
    
    def hailstone_it(n):
        return hailstone_it_helper(n, (), 0)
    
    在这里递归时,我们传入序列中的下一个n(取决于当前n是偶数还是奇数),以及到目前为止的结果

    一个更具python风格的解决方案 最后,因为在Python中通常不会编写这样的代码,所以让我们以一个更简单的例子来结束