Files

104 lines
3.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
If p is the perimeter of a right angle triangle with integral length sides,
{a, b, c} , there are exactly three solutions for p = 120.
{20,48,52},{24,45,51},{30,40,50}
For which value of p<=1000, is the number of solutions maximised?
"""
import time
import math
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} took time: {end_time - start_time:.6f} seconds")
return result
return wrapper
def generate_pythagorean_triples(max_perimeter: int = 1000) :
"""
使用yield生成勾股三元组的m和n参数
参数:
max_perimeter: 三角形周长的最大值
生成:
(m, n) 元组,满足:
- m > n > 0
- m和n互质 (gcd(m, n) == 1)
- m和n一奇一偶
- 三角形周长 2*m*(m+n) < max_perimeter
"""
# 从m=2开始因为m>n≥1
m = 2
while True:
# 对于每个mn从1到m-1
for n in range(1, m):
# 检查是否满足互质条件
if math.gcd(m, n) != 1:
continue
# 检查是否一奇一偶
if (m % 2) == (n % 2):
continue
# 计算对应三角形的周长
perimeter = 2 * m * (m + n)
# 如果周长超过限制,则停止生成
if perimeter >= max_perimeter:
# 对于当前m如果最小周长当n=1时已经超过限制
# 那么后续更大的m也会超过所以完全停止
if n == 1:
return
# 如果周长在限制内则yield当前(m, n)
if perimeter < max_perimeter:
yield (m, n)
m += 1
def triangle_length(m:int, n:int) -> int:
return 2 * m * (m + n)
def get_abc(m:int, n:int) -> tuple[int, int, int]:
a = m**2 - n**2
b = 2 * m * n
c = m**2 + n**2
return a, b, c
def primitive_triangles(limit: int = 1000) -> dict[int, list] :
triangle_lengths = {}
for m, n in generate_pythagorean_triples(limit):
length = triangle_length(m, n)
if length not in triangle_lengths:
triangle_lengths[length] = set()
a,b,c = get_abc(m, n)
triangle_lengths[length].add((a, b, c))
for k in range(2, limit // length + 1) :
lenp = k * (a + b + c)
if lenp not in triangle_lengths:
triangle_lengths[lenp] = set()
triangle_lengths[lenp].add((a*k, b*k, c*k))
return triangle_lengths
@timer
def main():
max_perimeter = 1000
triangle_lengths = primitive_triangles(max_perimeter)
print(triangle_lengths)
max_length = max(triangle_lengths, key=lambda x: len(triangle_lengths[x]))
print(f"Max length: {max_length}, Count: {len(triangle_lengths[max_length])}")
if __name__ == "__main__":
main()