""" 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]: """将三个列表的每个元素组合成数字""" 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(): print(sum(TruncatablePrime())) if __name__ == "__main__": main()