Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/powerbi/2.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 如何改进euler 14的代码?_Python - Fatal编程技术网

Python 如何改进euler 14的代码?

Python 如何改进euler 14的代码?,python,Python,我解决了,但我使用的程序非常慢。我看了看其他人做了什么,他们都提出了优雅的解决方案。我试图理解他们的代码,但没有成功 这是我的代码(用于确定Collatz链长度的函数 def collatz(n): a=1 while n!=1: if n%2==0: n=n/2 else: n=3*n+1 a+=1 return a 然后我使用了蛮力。它很慢,我知道它很弱。有人能告诉我为什么我的代码很弱,以及我如何用简单的英语改进我的代码吗。 请记住,

我解决了,但我使用的程序非常慢。我看了看其他人做了什么,他们都提出了优雅的解决方案。我试图理解他们的代码,但没有成功

这是我的代码(用于确定Collatz链长度的函数

def collatz(n):
a=1
while n!=1:
    if n%2==0:
        n=n/2
    else:
        n=3*n+1
    a+=1
return a
然后我使用了蛮力。它很慢,我知道它很弱。有人能告诉我为什么我的代码很弱,以及我如何用简单的英语改进我的代码吗。
请记住,我是一名初学者,我的编程技能是基本的。

与其从头到尾计算每个可能的链,不如保留链起点及其结果长度的缓存。例如

13 40  20  10  5  16  8  4  2  1
你可以记住以下几点:

  • 以13开头的Collatz链的长度为10
  • 以40开头的Collatz链的长度为9
  • 从20开始的Collatz链的长度为8
  • ……等等

    然后,一旦我们遇到缓存中已经存在的数字,我们就可以使用保存的信息停止计算链

    实施 使用Python中的字典将起始数字与其链长度关联:

    chain_sizes = {}
    chain_sizes[13] = 10
    chain_sizes[40] = 9
    chain_sizes[40]   # => 9
    20 in chain_sizes # => False
    
    现在,您只需调整算法以使用此字典(用值填充它并查找中间数字)


    顺便说一句,这可以用递归很好地表达。这里可能出现的链大小不会溢出堆栈:)

    简单地说,因为我的英语很糟糕;-)

    可以一次计算几个连续的迭代

    以k
    0
    位结尾的数字的第k次迭代:

    C^k(a*2^k) = a
    
    C^(2k)(a*2^k + 2^k - 1) = a*3^k + 3^k - 1 = (a + 1)*3^k - 1
    
    以k
    1
    位结尾的数字的第(2k)次迭代:

    C^k(a*2^k) = a
    
    C^(2k)(a*2^k + 2^k - 1) = a*3^k + 3^k - 1 = (a + 1)*3^k - 1
    
    比照公式;另请参见我的Python包中的(法语)和模块

    将以下代码与Niklas B解释的记忆技术相结合:

    #!/usr/bin/env python
    # -*- coding: latin-1 -*-
    from __future__ import division  # Python 3 style in Python 2
    from __future__ import print_function  # Python 3 style in Python 2
    
    
    def C(n):
        """Pre: n: int >= 1
        Result: int >= 1"""
        return (n//2 if n%2 == 0
                else n*3 + 1)
    
    
    def Ck(n, k):
        """Pre: n: int >= 1
             k: int >= 0
        Result: int >= 1"""
        while k > 0:
            while (n%2 == 0) and k:  # n even
                n //= 2
                k -= 1
    
            if (n == 1) and k:
                n = 4
                k -= 1
            else:
                nb = 0
                while (n > 1) and n%2 and (k > 1):  # n odd != 1
                    n //= 2
                    nb += 1
                    k -= 2
    
                if n%2 and (k == 1):
                    n = (n + 1)*(3**(nb + 1)) - 2
                    k -= 1
                elif nb:
                    n = (n + 1)*(3**nb) - 1
    
        return n
    
    
    def C_length(n):
        """Pre: n: int >= 1
        Result: int >= 1"""
        l = 1
    
        while n > 1:
            while (n > 1) and (n%2 == 0):  # n even
                n //= 2
                l += 1
    
            nb = 0
            while (n > 1) and n%2:  # n odd != 1
                n //= 2
                nb += 1
                l += 2
            if nb:
                n = (n + 1)*(3**nb) - 1
    
        return l
    
    
    if __name__ == '__main__':
        for n in range(1, 51):
            print(n, ': length =', C_length(n))
    

    当你在Project Euler上解决一项任务时(即使代码效率很低),你也可以下载一份pdf文档,解释如何最有效地解决该任务。正如你所知,到目前为止,你已经问了六个问题,其中许多问题都有很好的答案。“接受”一个能解决你问题的答案是很好的礼仪。您可以通过单击最佳答案下方的复选标记来完成此操作。你应该回去为你的旧答案做这件事;我相信帮助过你的人会很感激的。非常感谢我重新编写了我的程序,现在需要11.1秒。我想它仍然可以改进,但相比85秒,waw。我真得绞尽脑汁想办法,但现在没事了。Niklas B你太棒了。