feat: 添加欧拉计划第49题“素数排列”的Python解法

This commit is contained in:
2026-03-03 18:10:27 +08:00
parent 20b095e48a
commit cc6b5a1fbf

View File

@@ -0,0 +1,85 @@
"""
The arithmetic sequence, 1487,4817,8147, in which each of the terms increases by 3330,
is unusual in two ways: (i) each of the three terms are prime, and, (ii) each of the
4-digit numbers are permutations of one another.
There are no arithmetic sequences made up of three 1-, 2-, or 3-digit primes, exhibiting this property,
but there is one other 4-digit increasing sequence.
What 12-digit number do you form by concatenating the three terms in this sequence?
"""
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
elapsed_time = end_time - start_time
print(f"{func.__name__} time: {elapsed_time:.6f} seconds")
return result
return wrapper
def list_primes(start: int, end: int) -> list[int]:
# 只需要筛到 sqrt(9999) ≈ 100 即可标记合数
limit = int(end**0.5) + 1
base_primes = [True] * limit
base_primes[0] = base_primes[1] = False
# 生成基础质数2到100
for i in range(2, int(limit**0.5) + 1):
if base_primes[i]:
for j in range(i * i, limit, i):
base_primes[j] = False
# 分段筛只标记1000-9999范围
size = end - start + 1
is_prime = [True] * size
for p in range(2, limit):
if base_primes[p]:
# 找到第一个大于等于start的p的倍数
first = max(p * p, ((start + p - 1) // p) * p)
for j in range(first, end + 1, p):
is_prime[j - start] = False
return [i + start for i, val in enumerate(is_prime) if val]
def list_com(a: list, b: list) -> bool:
if len(set(a)) != len(set(b)):
return False
xb = b.copy()
for x in a:
if x not in xb:
return False
else:
xb.remove(x)
return True
@timer
def main():
primes = list_primes(1000, 9999)
max_sp = max(primes)
res = []
for i, v in enumerate(primes):
if v == max_sp:
break
gap = int((max_sp - v) / 3)
for g in range(gap, (primes[i + 1] - v - 1), -1):
if v + g in primes and v + 2 * g in primes:
if list_com(list(str(v)), list(str(v + g))):
if list_com(list(str(v)), list(str(v + 2 * g))):
res.append(str(v) + str(v + g) + str(v + 2 * g))
else:
continue
print(res)
if __name__ == "__main__":
main()