这是我写的计算毕达哥拉斯三胞胎的程序。当我运行程序时,由于if语句,它会打印两组三元组。有什么办法我可以告诉程序只打印一组新的三元组吗?感谢。
import math
def main():
for x in range (1, 1000):
for y in range (1, 1000):
for z in range(1, 1000):
if x*x == y*y + z*z:
print y, z, x
print '-'*50
if __name__ == '__main__':
main()
答案 0 :(得分:72)
Pythagorean Triples为声称“ for
循环被视为有害”提供了一个很好的例子,因为for
循环引诱我们思考计数,通常是最无关紧要的部分任务。
(我将坚持使用伪代码来避免语言偏差,并且为了简化伪代码,我不会优化掉例如x * x
和y * y
的多个计算。 )
版本1 :
for x in 1..N {
for y in 1..N {
for z in 1..N {
if x * x + y * y == z * z then {
// use x, y, z
}
}
}
}
是最糟糕的解决方案。它生成重复项,并遍历空间中无用的部分(例如,每当z < y
时)。它的时间复杂度在N
上是立方的。
版本2 ,第一项改进来自要求x < y < z
保留,如:
for x in 1..N {
for y in x+1..N {
for z in y+1..N {
if x * x + y * y == z * z then {
// use x, y, z
}
}
}
}
可减少运行时间并消除重复的解决方案。但是,它仍然是N
的立方;改善只是降低了N
- 立方体的系数。
在z
不再成立后继续检查z * z < x * x + y * y
的增加值是毫无意义的。这个事实激发了第3版,这是远离z
的蛮力迭代的第一步:
for x in 1..N {
for y in x+1..N {
z = y + 1
while z * z < x * x + y * y {
z = z + 1
}
if z * z == x * x + y * y and z <= N then {
// use x, y, z
}
}
}
对于1000的N
,这比版本2快5倍,但在N
上仍立方。
下一个见解是x
和y
是唯一的自变量; z
取决于其值,并且为z
的上一个值考虑的最后y
值是{em>开始搜索值的下一个值{{ 1}}。这导致版本4 :
y
允许for x in 1..N {
y = x+1
z = y+1
while z <= N {
while z * z < x * x + y * y {
z = z + 1
}
if z * z == x * x + y * y and z <= N then {
// use x, y, z
}
y = y + 1
}
}
和y
仅“扫描”z
以上的值一次。它不仅比x
1000快100多倍,而且在N
上是二次方,因此加速随着N
的增长而增加。
我经常遇到这种改进,经常不信任“计数循环”,除了最简单的用途(例如遍历数组)。
更新:显然我应该指出一些容易被忽视的关于V4的事情。
N
循环的两个都由while
的值控制(一个直接,另一个通过z
的平方间接控制) 。内部z
实际上正在加速外部while
,而不是与它正交。 了解循环的作用非常重要,而不仅仅是计算循环次数。
V4中的所有计算都是严格的整数运算。相比之下,转换到浮点或从浮点计算转换成本很高。
V4在常量内存中运行,只需要三个整数变量。没有要分配和初始化的数组或散列表(并且可能导致内存不足错误)。
原始问题允许所有while
,x
和y
在同一范围内变化。 V1..V4遵循该模式。
下面是一组非常科学的时序(在我的旧笔记本电脑上使用Eclipse下运行其他东西的Java ...),其中“使用x,y,z”是通过实例化一个Triple对象来实现的。这三个值并将其放入ArrayList中。 (对于这些运行,x
设置为10,000,每种情况下产生12,471个三元组。)
N
“数组和地图”算法基本上是 :
Version 4: 46 sec.
using square root: 134 sec.
array and map: 400 sec.
“使用平方根”算法基本上是:
squares = array of i*i for i in 1 .. N
roots = map of i*i -> i for i in 1 .. N
for x in 1 .. N
for y in x+1 .. N
z = roots[squares[x] + squares[y]]
if z exists use x, y, z
V4的实际代码是:
for x in 1 .. N
for y in x+1 .. N
z = (int) sqrt(x * x + y * y)
if z * z == x * x + y * y then use x, y, z
请注意,在外部循环中计算public Collection<Triple> byBetterWhileLoop() {
Collection<Triple> result = new ArrayList<Triple>(limit);
for (int x = 1; x < limit; ++x) {
int xx = x * x;
int y = x + 1;
int z = y + 1;
while (z <= limit) {
int zz = xx + y * y;
while (z * z < zz) {++z;}
if (z * z == zz && z <= limit) {
result.add(new Triple(x, y, z));
}
++y;
}
}
return result;
}
(尽管我没有费心去缓存x * x
);在其他变体中也进行了类似的优化。
我很乐意根据请求提供Java源代码,以便在我错误实现任何内容的情况下为其他变体提供。
答案 1 :(得分:40)
到目前为止,它比任何解决方案都要快得多。通过三元树找到三胞胎。
Wolfram说:
霍尔(1970年)和罗伯茨(1977年)证明这是一个原始的毕达哥拉斯三重奏,当且仅当
(a,b,c)=(3,4,5)M
其中M是矩阵U,A,D的有限乘积。
我们有一个公式来生成每个原始三元组。
在上面的公式中,斜边不断增长,因此检查最大长度非常容易。
在Python中:
import numpy as np
def gen_prim_pyth_trips(limit=None):
u = np.mat(' 1 2 2; -2 -1 -2; 2 2 3')
a = np.mat(' 1 2 2; 2 1 2; 2 2 3')
d = np.mat('-1 -2 -2; 2 1 2; 2 2 3')
uad = np.array([u, a, d])
m = np.array([3, 4, 5])
while m.size:
m = m.reshape(-1, 3)
if limit:
m = m[m[:, 2] <= limit]
yield from m
m = np.dot(m, uad)
如果您喜欢所有三元组而不仅仅是原语:
def gen_all_pyth_trips(limit):
for prim in gen_prim_pyth_trips(limit):
i = prim
for _ in range(limit//prim[2]):
yield i
i = i + prim
list(gen_prim_pyth_trips(10**4))
需要2.81毫秒才能返回1593个元素,而list(gen_all_pyth_trips(10**4))
需要19.8毫秒才能返回12471个元素
作为参考,accepted answer (in python)为12471个元素花费了38秒。
只是为了好玩,将上限设置为一百万list(gen_all_pyth_trips(10**6))
,在2.66秒内返回1980642元素(3秒内几乎200万三倍)。 list(gen_all_pyth_trips(10**7))
使我的计算机瘫痪,因为列表变得如此之大,它消耗了最后一点ram。像sum(1 for _ in gen_all_pyth_trips(10**7))
这样的事情绕过了这个限制,并在30秒内返回23471475个元素。
答案 2 :(得分:13)
你应该定义x&lt; y&lt; ž。
for x in range (1, 1000):
for y in range (x + 1, 1000):
for z in range(y + 1, 1000):
另一个好的优化是仅使用x和y并计算zsqr = x * x + y * y。如果zsqr是一个平方数(或z = sqrt(zsqr)是整数),则它是三元组,否则不是。这样,您只需要两个循环而不是三个循环(例如,大约快了1000倍)。
答案 3 :(得分:11)
之前列出的生成Pythagorean triplets的算法是从基本关系a^2 + b^2 = c^2
派生的朴素方法的所有修改,其中(a, b, c)
是正整数的三元组。事实证明,毕达哥拉斯三胞胎满足了一些相当显着的关系,可以用来生成所有毕达哥拉斯三胞胎。
Euclid发现了第一个这样的关系。他确定,对于每个毕达哥拉斯三重(a, b, c)
,可能在重新排序a
和b
之后,有m
和n
m > n
和k
其中至少有一个是偶数,而正整数a = k (2mn)
b = k (m^2 - n^2)
c = k (m^2 + n^2)
就是
m
然后生成毕达哥拉斯三元组,生成不同奇偶校验的相对正整数n
和k
,以及正整数struct PythagoreanTriple {
public int a { get; private set; }
public int b { get; private set; }
public int c { get; private set; }
public PythagoreanTriple(int a, int b, int c) : this() {
this.a = a < b ? a : b;
this.b = b < a ? a : b;
this.c = c;
}
public override string ToString() {
return String.Format("a = {0}, b = {1}, c = {2}", a, b, c);
}
public static IEnumerable<PythagoreanTriple> GenerateTriples(int max) {
var triples = new List<PythagoreanTriple>();
for (int m = 1; m <= max / 2; m++) {
for (int n = 1 + (m % 2); n < m; n += 2) {
if (m.IsRelativelyPrimeTo(n)) {
for (int k = 1; k <= max / (m * m + n * n); k++) {
triples.Add(EuclidTriple(m, n, k));
}
}
}
}
return triples;
}
private static PythagoreanTriple EuclidTriple(int m, int n, int k) {
int msquared = m * m;
int nsquared = n * n;
return new PythagoreanTriple(k * 2 * m * n, k * (msquared - nsquared), k * (msquared + nsquared));
}
}
public static class IntegerExtensions {
private static int GreatestCommonDivisor(int m, int n) {
return (n == 0 ? m : GreatestCommonDivisor(n, m % n));
}
public static bool IsRelativelyPrimeTo(this int m, int n) {
return GreatestCommonDivisor(m, n) == 1;
}
}
class Program {
static void Main(string[] args) {
PythagoreanTriple.GenerateTriples(1000).ToList().ForEach(t => Console.WriteLine(t));
}
}
并应用上述公式。
{{1}}
关于Formulas for generating Pythagorean triples的维基百科文章包含其他此类公式。
答案 4 :(得分:8)
可以针对速度,内存使用,简单性等方面调整算法。
这是一个针对速度而调整的pythagore_triplets
算法,代价是内存使用和简单性。如果你想要的只是速度,这可能就是你要走的路。
list(pythagore_triplets(10000))
的计算在我的计算机上需要40秒,而ΤΖΩΤΖΙΟΥ算法需要63秒,并且可能需要几天计算Tafkas的算法(以及使用3个嵌入式循环而不仅仅是2个的所有其他算法)。
def pythagore_triplets(n=1000):
maxn=int(n*(2**0.5))+1 # max int whose square may be the sum of two squares
squares=[x*x for x in xrange(maxn+1)] # calculate all the squares once
reverse_squares=dict([(squares[i],i) for i in xrange(maxn+1)]) # x*x=>x
for x in xrange(1,n):
x2 = squares[x]
for y in xrange(x,n+1):
y2 = squares[y]
z = reverse_squares.get(x2+y2)
if z != None:
yield x,y,z
>>> print list(pythagore_triplets(20))
[(3, 4, 5), (5, 12, 13), (6, 8, 10), (8, 15, 17), (9, 12, 15), (12, 16, 20)]
请注意,如果您要计算前十亿个三元组,那么由于内存不足错误,此算法在启动之前会崩溃。因此,对于高值n,ΤΖΩΤΖΙΟΥ的算法可能是更安全的选择。
顺便说一句,这是Tafkas的算法,为了我的性能测试而翻译成python。它的缺陷是需要3个循环而不是2个循环。def gcd(a, b):
while b != 0:
t = b
b = a%b
a = t
return a
def find_triple(upper_boundary=1000):
for c in xrange(5,upper_boundary+1):
for b in xrange(4,c):
for a in xrange(3,b):
if (a*a + b*b == c*c and gcd(a,b) == 1):
yield a,b,c
答案 5 :(得分:6)
def pyth_triplets(n=1000):
"Version 1"
for x in xrange(1, n):
x2= x*x # time saver
for y in xrange(x+1, n): # y > x
z2= x2 + y*y
zs= int(z2**.5)
if zs*zs == z2:
yield x, y, zs
>>> print list(pyth_triplets(20))
[(3, 4, 5), (5, 12, 13), (6, 8, 10), (8, 15, 17), (9, 12, 15), (12, 16, 20)]
V.1算法具有单调递增的x
值。
看来这个问题还活着:) 自从我回来并重新访问代码之后,我尝试了第二种方法,这几乎是我之前建议的4倍(大约26%的CPU时间为N = 10000),因为它避免了大量不必要的计算:
def pyth_triplets(n=1000):
"Version 2"
for z in xrange(5, n+1):
z2= z*z # time saver
x= x2= 1
y= z - 1; y2= y*y
while x < y:
x2_y2= x2 + y2
if x2_y2 == z2:
yield x, y, z
x+= 1; x2= x*x
y-= 1; y2= y*y
elif x2_y2 < z2:
x+= 1; x2= x*x
else:
y-= 1; y2= y*y
>>> print list(pyth_triplets(20))
[(3, 4, 5), (6, 8, 10), (5, 12, 13), (9, 12, 15), (8, 15, 17), (12, 16, 20)]
请注意,此算法的值增加z
。
如果算法转换为C -where,更接近金属,乘法比加法需要更多的时间 - 考虑到连续正方形之间的步长为:
,可以将必要的乘法最小化(x + 1)² - x²=(x + 1)(x + 1) - x²=x²+ 2x + 1 - x²= 2x + 1
因此所有内部x2= x*x
和y2= y*y
都会转换为加法和减法,如下所示:
def pyth_triplets(n=1000):
"Version 3"
for z in xrange(5, n+1):
z2= z*z # time saver
x= x2= 1; xstep= 3
y= z - 1; y2= y*y; ystep= 2*y - 1
while x < y:
x2_y2= x2 + y2
if x2_y2 == z2:
yield x, y, z
x+= 1; x2+= xstep; xstep+= 2
y-= 1; y2-= ystep; ystep-= 2
elif x2_y2 < z2:
x+= 1; x2+= xstep; xstep+= 2
else:
y-= 1; y2-= ystep; ystep-= 2
当然,在Python中,与版本2相比,生成的额外字节码实际上减慢了算法,但我敢打赌(不检查:) V.3在C中更快。
为每个人欢呼:)
答案 6 :(得分:4)
我对Kyle Gullion的回答进行了扩展,以便将三元组分类为hypothenuse,然后是最长的一侧。
它不使用numpy,但需要SortedCollection(或SortedList),例如this one
def primitive_triples():
""" generates primitive Pythagorean triplets x<y<z
sorted by hypotenuse z, then longest side y
through Berggren's matrices and breadth first traversal of ternary tree
:see: https://en.wikipedia.org/wiki/Tree_of_primitive_Pythagorean_triples
"""
key=lambda x:(x[2],x[1])
triples=SortedCollection(key=key)
triples.insert([3,4,5])
A = [[ 1,-2, 2], [ 2,-1, 2], [ 2,-2, 3]]
B = [[ 1, 2, 2], [ 2, 1, 2], [ 2, 2, 3]]
C = [[-1, 2, 2], [-2, 1, 2], [-2, 2, 3]]
while triples:
(a,b,c) = triples.pop(0)
yield (a,b,c)
# expand this triple to 3 new triples using Berggren's matrices
for X in [A,B,C]:
triple=[sum(x*y for (x,y) in zip([a,b,c],X[i])) for i in range(3)]
if triple[0]>triple[1]: # ensure x<y<z
triple[0],triple[1]=triple[1],triple[0]
triples.insert(triple)
def triples():
""" generates all Pythagorean triplets triplets x<y<z
sorted by hypotenuse z, then longest side y
"""
prim=[] #list of primitive triples up to now
key=lambda x:(x[2],x[1])
samez=SortedCollection(key=key) # temp triplets with same z
buffer=SortedCollection(key=key) # temp for triplets with smaller z
for pt in primitive_triples():
z=pt[2]
if samez and z!=samez[0][2]: #flush samez
while samez:
yield samez.pop(0)
samez.insert(pt)
#build buffer of smaller multiples of the primitives already found
for i,pm in enumerate(prim):
p,m=pm[0:2]
while True:
mz=m*p[2]
if mz < z:
buffer.insert(tuple(m*x for x in p))
elif mz == z:
# we need another buffer because next pt might have
# the same z as the previous one, but a smaller y than
# a multiple of a previous pt ...
samez.insert(tuple(m*x for x in p))
else:
break
m+=1
prim[i][1]=m #update multiplier for next loops
while buffer: #flush buffer
yield buffer.pop(0)
prim.append([pt,2]) #add primitive to the list
代码位于math2 module的my Python library。它针对OEIS的一些系列进行了测试(底部的代码here),这使我能够find a mistake in A121727: - )
答案 7 :(得分:2)
我在Ruby中编写了该程序,它类似于python实现。重要的一点是:
if x*x == y*y + z*z && gcd(y,z) == 1:
然后你必须实现一个返回两个给定数字的最大公约数(gcd)的方法。 Ruby中的一个非常简单的例子:
def gcd(a, b)
while b != 0
t = b
b = a%b
a = t
end
return a
end
找到三胞胎的完整Ruby方法将是:
def find_triple(upper_boundary)
(5..upper_boundary).each {|c|
(4..c-1).each {|b|
(3..b-1).each {|a|
if (a*a + b*b == c*c && gcd(a,b) == 1)
puts "#{a} \t #{b} \t #{c}"
end
}
}
}
end
答案 8 :(得分:1)
在python中,我们可以将所有数字的平方存储在另一个列表中。 然后找到给定的所有数字对的排列 平方它们 最后检查任何一对平方和是否与平方列表匹配
答案 9 :(得分:1)
是的,有。
好的,现在你想知道原因。为什么不限制它以便z> ÿ?试试
for z in range (y+1, 1000)
答案 10 :(得分:1)
for a in range(1,20):
for b in range(1,20):
for c in range(1,20):
if a>b and c and c>b:
if a**2==b**2+c**2:
print("triplets are:",a,b,c)
答案 11 :(得分:1)
from math import sqrt
from itertools import combinations
#Pythagorean triplet - a^2 + b^2 = c^2 for (a,b) <= (1999,1999)
def gen_pyth(n):
if n >= 2000 :
return
ELEM = [ [ i,j,i*i + j*j ] for i , j in list(combinations(range(1, n + 1 ), 2)) if sqrt(i*i + j*j).is_integer() ]
print (*ELEM , sep = "\n")
gen_pyth(200)
答案 12 :(得分:1)
旧问题,但我仍会输入我的东西。 有两种生成独特的毕达哥拉斯三元组的一般方法。一个是通过缩放,另一个是使用这个古老的公式。
什么缩放基本上需要一个常数n,然后乘以一个基本三元组,比如说3,4,5乘以n。所以将n设为2,我们得到6,8,10我们的下一个三联。
<强>缩放强>
def pythagoreanScaled(n):
triplelist = []
for x in range(n):
one = 3*x
two = 4*x
three = 5*x
triple = (one,two,three)
triplelist.append(triple)
return triplelist
公式方法使用的事实是,如果我们取一个数x,计算2m,m ^ 2 + 1和m ^ 2-1,那三个将永远是毕达哥拉斯三元组。
<强>式强>
def pythagoreantriple(n):
triplelist = []
for x in range(2,n):
double = x*2
minus = x**2-1
plus = x**2+1
triple = (double,minus,plus)
triplelist.append(triple)
return triplelist
答案 13 :(得分:0)
应该注意的是,对于a,b和c,您不需要一直循环到N.
对于a,您只需要从1循环到int(sqrt(n**2/2))+1
,对于b,a+1
到int(sqrt(n**2-a**2))+1
,对于从int(sqrt(a**2+b**2)
到int(sqrt(a**2+b**2)+2
的c循环
答案 14 :(得分:0)
# To find all pythagorean triplets in a range
import math
n = int(input('Enter the upper range of limit'))
for i in range(n+1):
for j in range(1, i):
k = math.sqrt(i*i + j*j)
if k % 1 == 0 and k in range(n+1):
print(i,j,int(k))
答案 15 :(得分:0)
您可以尝试
triplets=[]
for a in range(1,100):
for b in range(1,100):
for c in range(1,100):
if a**2 + b**2==c**2:
i=[a,b,c]
triplets.append(i)
for i in triplets:
i.sort()
if triplets.count(i)>1:
triplets.remove(i)
print(triplets)
答案 16 :(得分:0)
您必须使用欧几里得的毕达哥拉斯三胞胎证明。请在下面...
U可以选择大于零的任意数字,例如m,n
根据Euclid,三元组将是a(m*m-n*n)
,b(2*m*n)
,c(m*m+n*n)
现在应用这个公式找出三胞胎,说我们的三胞胎的值是6,那么另外两个呢?好,让我们解决...
a(m*m-n*n)
,b(2*m*n)
,c(m*m+n*n)
确定b(2*m*n)
显然是偶数。所以现在
(2*m*n)=6 =>(m*n)=3 =>m*n=3*1 =>m=3,n=1
U可以采用除3和1以外的任何其他值,但是这两个值应包含两个数字的乘积3 (m*n=3)
现在,当m=3
和n=1
之后,
a(m*m-n*n)=(3*3-1*1)=8
,c(m*m-n*n)=(3*3+1*1)=10
6,8,10是我们的三元组,这是我们如何生成三元组的可视化。
如果给定的数字像(9)
一样是奇数,则在此处稍作修改,因为b(2*m*n)
永远不会是奇数。所以,这里我们必须采取
a(m*m-n*n)=7
,(m+n)*(m-n)=7*1
,(m+n)=7
,(m-n)=1
现在从此处找到m和n,然后找到其他两个值。
如果您不理解,请仔细阅读。
按照此代码进行编码,它将有效地生成不同的三元组。
答案 17 :(得分:0)
只是检查,但我一直在使用以下代码制作毕达哥拉斯三元组。这是非常快的(我已经尝试了一些这里的例子,虽然我有点学习它们并自己编写并回来检查这里(2年前))。我认为这段代码正确地找到所有毕达哥拉斯三元组(命名你的极限)并且相当快。我用C ++来制作它。
ullong是unsigned long long,我创建了几个square和root函数 我的root函数基本上说如果给定数字的平方根(在使它成为整数(整数)之后)平方不等于数给予然后返回-1因为它不是可root的。 _square和_root如上所述按预期执行,我知道另一种优化方法,但我还没有做过,也没有测试过。
generate(vector<Triple>& triplist, ullong limit) {
cout<<"Please wait as triples are being generated."<<endl;
register ullong a, b, c;
register Triple trip;
time_t timer = time(0);
for(a = 1; a <= limit; ++a) {
for(b = a + 1; b <= limit; ++b) {
c = _root(_square(a) + _square(b));
if(c != -1 && c <= limit) {
trip.a = a; trip.b = b; trip.c = c;
triplist.push_back(trip);
} else if(c > limit)
break;
}
}
timer = time(0) - timer;
cout<<"Generated "<<triplist.size()<<" in "<<timer<<" seconds."<<endl;
cin.get();
cin.get();
}
让我知道你们都在想什么。它根据我转过身来的老师生成所有原始和非原始三元组。 (如果我没记错的话,她会把它测试到100)。
前一个编码器提供的v4的结果是
下面是一组非常科学的时序(在我的旧笔记本电脑上使用Eclipse下运行其他东西的Java ...),其中“使用x,y,z”是通过实例化一个Triple对象来实现的。这三个值并将其放入ArrayList中。 (对于这些运行,N设置为10,000,在每种情况下产生12,471三倍。)
第4版:46秒 使用平方根:134秒。 数组和地图:400秒。
我的结果是 生成多少三倍:10000
请等待生成三元组。 在2秒内生成12471。
那是在我开始通过编译器进行优化之前。 (我记得先前有10000到0秒,有很多特殊选项和东西)。我的代码也会生成所有三元组,其中100,000为高限制1,2,可以在3.2分钟内完成(我认为1,000,000限制需要一个小时)。
我稍微修改了代码并将10,000限制降低到1秒(没有优化)。最重要的是,经过仔细考虑,我可以分解成块并在给定范围内进行线程化(例如,100,000个分成4个相等的块,用于3个cpu(1个额外的,希望消耗cpu时间以防万一),范围为1到25,000 (从1开始,限制为25,000),25,000到50,000,50,000到75,000,以及75,000结束。我可以这样做,看看它是否加速了(我将预制线程,不包括实际数量)时间来执行三重函数。我需要一个更精确的计时器和一种连接向量的方法。我认为如果1个3.4 GHZ cpu和8 gb ram处理它可以在1秒内完成10,000作为lim,然后是3 cpus应该在1/3秒内做到这一点(并且我按原样转向更高的秒)。
答案 18 :(得分:0)
Hall / Roberts方法的非数字化版本是
def pythag3(limit=None, all=False):
"""generate Pythagorean triples which are primitive (default)
or without restriction (when ``all`` is True). The elements
returned in the tuples are sorted with the smallest first.
Examples
========
>>> list(pythag3(20))
[(3, 4, 5), (8, 15, 17), (5, 12, 13)]
>>> list(pythag3(20, True))
[(3, 4, 5), (6, 8, 10), (9, 12, 15), (12, 16, 20), (8, 15, 17), (5, 12, 13)]
"""
if limit and limit < 5:
return
m = [(3,4,5)] # primitives stored here
while m:
x, y, z = m.pop()
if x > y:
x, y = y, x
yield (x, y, z)
if all:
a, b, c = x, y, z
while 1:
c += z
if c > limit:
break
a += x
b += y
yield a, b, c
# new primitives
a = x - 2*y + 2*z, 2*x - y + 2*z, 2*x - 2*y + 3*z
b = x + 2*y + 2*z, 2*x + y + 2*z, 2*x + 2*y + 3*z
c = -x + 2*y + 2*z, -2*x + y + 2*z, -2*x + 2*y + 3*z
for d in (a, b, c):
if d[2] <= limit:
m.append(d)
它比numpy编码的版本慢,但是在我的慢速计算机上大约需要1.4秒的时间来生成最大元素小于或等于10^6
的基元。 (而且列表m
从未超过18个元素。)
答案 19 :(得分:0)
Joel Neely的第5版。
因为X可以是'N-2'的最大值,并且对于1..N的范围,Y可以是'N-1'的最大值。由于Z max为N且Y max为N-1,因此X可以是Sqrt(N * N - (N-1)*(N-1))= Sqrt(2 * N - 1)的最大值,并且可以从3开始
MaxX = ( 2 * N - 1 ) ** 0.5
for x in 3..MaxX {
y = x+1
z = y+1
m = x*x + y*y
k = z * z
while z <= N {
while k < m {
z = z + 1
k = k + (2*z) - 1
}
if k == m and z <= N then {
// use x, y, z
}
y = y + 1
m = m + (2 * y) - 1
}
}