""" If we take 47, reverse and add, 47 + 74 = 121, which is palindromic. Not all numbers produce palindromes so quickly. For example, 349 + 943 = 1292 1292 + 2921 = 4213 4213 + 3124 = 7337 That is, 349 took three iterations to arrive at a palindrome. Although no one has proved it yet, it is thought that some numbers, like 196, never produce a palindrome. A number that never forms a palindrome through the reverse and add process is called a Lychrel number. Due to the theoretical nature of these numbers, and for the purpose of this problem, we shall assume that a number is Lychrel until proven otherwise. In addition you are given that for every number below ten-thousand, it will either (i) become a palindrome in less than fifty iterations, or, (ii) no one, with all the computing power that exists, has managed so far to map it to a palindrome. In fact, 10677 is the first number to be shown to require over fifty iterations before producing a palindrome: 4668731596684224866951378664 (53 iterations, 28-digits). Surprisingly, there are palindromic numbers that are themselves Lychrel numbers; the first example is 4994. How many Lychrel numbers are there below ten-thousand? NOTE: Wording was modified slightly on 24 April 2007 to emphasise the theoretical nature of Lychrel numbers. """ import time from functools import wraps from typing import Any, Callable, TypeVar F = TypeVar("F", bound=Callable[..., Any]) def benchmark(repeat: int = 1) -> Callable[[F], F]: """ 重复运行目标函数并计算平均耗时。 平均耗时会被存储在 wrapper.avg_time 和 wrapper.total_time 中, 同时会打印到控制台。函数的返回值不受影响。 """ if repeat < 1: raise ValueError("repeat 必须 >= 1") def decorator(func: F) -> F: @wraps(func) def wrapper(*args: Any, **kwargs: Any) -> Any: total = 0.0 result = None for _ in range(repeat): start = time.perf_counter() result = func(*args, **kwargs) end = time.perf_counter() total += end - start wrapper.avg_time = total / repeat # type: ignore[attr-defined] wrapper.total_time = total # type: ignore[attr-defined] print( f"[Benchmark] {func.__name__} | 重复 {repeat} 次 | " f"平均: {wrapper.avg_time:.6f}s | 总计: {wrapper.total_time:.6f}s" # type: ignore[attr-defined] ) return result # 初始化属性,避免调用前访问报错 wrapper.avg_time = 0.0 # type: ignore[attr-defined] wrapper.total_time = 0.0 # type: ignore[attr-defined] return wrapper # type: ignore[return-value] return decorator def is_palindrome(n): return str(n) == str(n)[::-1] def is_lychrel(n, max_iterations=50): for _ in range(max_iterations): n += int(str(n)[::-1]) if is_palindrome(n): return False return True @benchmark(repeat=15) def count_lychrel_numbers(limit): count = 0 for n in range(1, limit + 1): if is_lychrel(n): count += 1 return count if __name__ == "__main__": result = count_lychrel_numbers(10000) print(f"Number of Lychrel numbers below 10,000: {result}")