Files
SolutionEuler/solutions/0037.TruncatablePrimes/euler_37.py
Sidney Zhang 745989cb32 feat(euler_37.py):修复combine_lists函数处理空列表的情况,并改进输出格式显示每个截断素数
📝 docs(0037.TruncatablePrimes):添加readme.md文档解释截断素数只有11个的原因
 feat(euler_38.py):新增全数字倍数问题的解决方案,包含优化算法和详细注释
2026-01-08 14:38:53 +08:00

93 lines
2.4 KiB
Python

"""
The number 3797 has an interesting property.
Being prime itself, it is possible to continuously remove digits from left to right,
and remain prime at each stage: 3797, 797, 97, and 7.
Similarly we can work from right to left: 3797, 379, 37, and 3.
Find the sum of the only eleven primes that are both truncatable from left to right and right to left.
NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes.
"""
import time
from itertools import product
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"Time taken: {end_time - start_time:.6f} seconds")
return result
return wrapper
def combine_lists(a: list[int], b: list[int | None], c: list[int]) -> list[int]:
"""将三个列表的每个元素组合成数字"""
if b in [[],[None]] :
return [int(f"{x}{z}") for x, z in product(a, c)]
return [int(f"{x}{y}{z}") for x, y, z in product(a, b, c)]
def is_prime(n: int) -> bool:
"""判断一个数是否为素数"""
if n < 2:
return False
for i in range(2, int(n**0.5) + 1):
if n % i == 0:
return False
return True
def truncate_left(n: int) -> bool:
"""从左到右截断一个数"""
length = len(str(n))
while n > 0:
if not is_prime(n):
return False
n %= 10 ** (length - 1)
length -= 1
return True
def truncate_right(n: int) -> bool:
"""从右到左截断一个数"""
while n > 0:
if not is_prime(n):
return False
n //= 10
return True
def TruncatablePrime() -> list[int]:
begin = [2, 3, 5, 7]
end = [3, 7]
middle = [1, 3, 7, 9]
res = []
for length in range(2, 7):
if length - 2 == 0:
midb = []
else:
midb = product(middle, repeat=length - 2)
midb = [int("".join(map(str, x))) for x in midb]
nums = combine_lists(begin, midb, end)
for num in nums:
if is_prime(num):
if truncate_left(num) and truncate_right(num):
res.append(num)
return res
@timer
def main():
nums = TruncatablePrime()
for num in nums:
print(num)
print(f"Answer: {sum(nums)}")
if __name__ == "__main__":
main()