Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/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脚本?_Python - Fatal编程技术网

如何优化这个Python脚本?

如何优化这个Python脚本?,python,Python,对于周长为p的整数直角三角形,有许多解(a,b,c),对于所有这些解,a+b+c==p,毕达哥拉斯定理也适用。我正在编写一个Python脚本来计算周长更好的三角形的最大可能解数: def solution(n): count = 0 for c in range(n // 3 + 1, n // 2): for a in range(1, n // 3): b = n - a - c if b <= 0:

对于周长为p的整数直角三角形,有许多解(a,b,c),对于所有这些解,a+b+c==p,毕达哥拉斯定理也适用。我正在编写一个Python脚本来计算周长更好的三角形的最大可能解数:

def solution(n):
    count = 0
    for c in range(n // 3 + 1, n // 2):
        for a in range(1, n // 3):
            b = n - a - c
            if b <= 0:
                continue
            if a >= b:
                continue
            if a * a + b * b != c * c:
                continue
            count += 1
    return count
def溶液(n):
计数=0
对于范围(n//3+1,n//2)内的c:
对于范围(1,n//3)内的a:
b=n-a-c
如果b=b:
持续
如果a*a+b*b!=c*c:
持续
计数+=1
返回计数

这是我对你的程序的重写

首先,我预先计算所有的平方值。这不仅避免了乘法运算,而且意味着Python不会不断地为所有平方值创建和垃圾收集对象

接下来,我去掉了三角形第三边的环。一旦您为
a
b
选择了值,则只有一个可能的值符合标准
a+b+c==1000
,因此这只是测试该值。这将问题从大约O(n^3)转化为大约O(n^2),这是一个巨大的改进

然后我试着运行它。在我用了四年的电脑上,它只用了大约46秒就完成了,所以我停在那里,给你

我在谷歌上搜索了一下,找到了关于这个问题的讨论;如果我看到的讨论是正确的,那么这个程序将打印正确的答案

upper_bound = 1000

sqr = [i**2 for i in range(upper_bound+1)]

def solutions(p):
    result = []

    for a in range(1, p - 1):
        for b in range(1, p - a):
            c = p - (a + b)
            if a < b < c:
                d = sqr[a]
                e = sqr[b]
                f = sqr[c]

                if (d + e == f) or (e + f == d) or (f + d == e):
                    result.append((a, b, c))
    return len(result)


max_p = 0
max_solutions = 0

for p in range(3, upper_bound+1):
    print("Processing %d" % p)
    s = solutions(p)

    if s > max_solutions:
        max_solutions = s
        max_p = p

print("%d has %d solutions" % (max_p, max_solutions))
在我的电脑上,这个版本需要31秒而不是46秒


使用
max()。我在没有预先计算正方形的情况下尝试了它,速度非常慢,我不想等待确切的时间。

明白了。它仅仅依赖于设置a^2+b^2=c^2,然后替换p-a-b=c

 1 from math import pow
  2 
  3 def see_if_right_triangle(p):
        solutions = 0
  4     # Accepts the perimeter as input
  5     for a in range(1, p): 
  6         for b in range(1, p):
  7             if 2*p*b + 2*p*a - pow(p, 2) == 2*a*b:
  8                solutions += 1
        print "The perimeter {p} has {sol} number of solutions".format(p=p, sol=solutions)
 10                        
 11 
 12 for p in range(3, 1001):
 13     see_if_right_triangle(p)

我认为这可以优化更多。。。特别是如果你计算出一些数学来缩小你将要接受的a和b的范围

这不是你的代码优化,而是我自己的代码(我用于这个问题)。我首先做了一些代数运算,使程序非常简单,不必迭代
1000^3次(a
为1-1000次,b
a
的每个值迭代1-1000次,c为
b
的每个值迭代1-1000次)

# Project Euler 9
'''
Algebra behind Final Method:
a + b + c = 1000 | a^2 + b^2 = c^2
c = 1000 - (a + b) # Solving for C
a^2 + b^2 = (1000 - (a + b))^2 # Substituting value for C
a^2 + b^2 = 1000000 - 2000a - 2000b + (a + b)^2 # simplifying
a^2 + b^2 = 1000000 - 2000a - 2000b + a^2 + b^2 + 2ab # simplifying again
0 = 1000000 - 2000a - 2000b + 2ab # new formula
2000a - 2ab = 1000000 - 2000b # isolating A
1000a - ab = 500000 - 1000b # divide by 2 to simplify
a(1000 - b) = 500000 - 1000b # factor out A
a = (500000 - 1000b) / (1000 - b) # solve for A
'''
def pE9():
   from math import sqrt
   a, b, c = 1, 1, 1
   while True:
      b += 1
      a = (500000 - 1000 * b) / (1000 - b)
      c = sqrt(a**2 + b**2)
      if a + b + c == 1000 and a**2 + b**2 == c**2:
         break
   print int(a * b * c)

from timeit import timeit
print timeit(pE9, number = 1)
使用
number=1
,只需测试一次即可

输出:

>>> 
# Answer hidden
0.0142664994414

这难道不更适合codereview.stackexchange.com吗?除非你要求一个更好的算法,在这种情况下,我想问题应该是语言不可知的。这甚至可以在数学stackexchangequick注释中进行,
a假设
c
是斜边,如果
a表示范围(a+1,p-a)中的b:
你不再需要测试
a
。d也可以从内部循环中移出。真的不需要这些
或(e+f==d)或(f+d==e)
为meLike减少了约60%的运行时间。我说过,当我得到答案时我停止了…:-)我认为最大的交易是摆脱N次方顺序行为。对于三角形,c应该小于
n/2
,它是一个直角三角形,所以c应该大于
n/3
。现在,如果最短边
a
大于
n/3
b
将为负值。
# Project Euler 9
'''
Algebra behind Final Method:
a + b + c = 1000 | a^2 + b^2 = c^2
c = 1000 - (a + b) # Solving for C
a^2 + b^2 = (1000 - (a + b))^2 # Substituting value for C
a^2 + b^2 = 1000000 - 2000a - 2000b + (a + b)^2 # simplifying
a^2 + b^2 = 1000000 - 2000a - 2000b + a^2 + b^2 + 2ab # simplifying again
0 = 1000000 - 2000a - 2000b + 2ab # new formula
2000a - 2ab = 1000000 - 2000b # isolating A
1000a - ab = 500000 - 1000b # divide by 2 to simplify
a(1000 - b) = 500000 - 1000b # factor out A
a = (500000 - 1000b) / (1000 - b) # solve for A
'''
def pE9():
   from math import sqrt
   a, b, c = 1, 1, 1
   while True:
      b += 1
      a = (500000 - 1000 * b) / (1000 - b)
      c = sqrt(a**2 + b**2)
      if a + b + c == 1000 and a**2 + b**2 == c**2:
         break
   print int(a * b * c)

from timeit import timeit
print timeit(pE9, number = 1)
>>> 
# Answer hidden
0.0142664994414