Files
SolutionEuler/solutions/0040.ChampernownesConstant/euler_40.py

92 lines
2.5 KiB
Python
Raw 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.

"""
An irrational decimal fraction is created by concatenating the positive integers:
0.123456789101112131415161718192021...
It can be seen that the 12th digit of the fractional part is 1.
If d_n represents the nth digit of the fractional part, find the value of the following expression.
d_1 × d_10 × d_100 × d_1000 × d_10000 × d_100000 × d_1000000
"""
import time
def timer(func):
def wrapper(*args, **kwargs):
start_time = time.time()
result = func(*args, **kwargs)
end_time = time.time()
print(f"{func.__name__} time: {end_time - start_time:.6f} seconds")
return result
return wrapper
class ChampernownesConstant:
def __init__(self):
self._cache = "123456789"
self._level = 1
self._nth = 1
def __iter__(self):
if self._nth > len(self._cache):
self._level += 1
self._cache += "".join(str(i) for i in range(10**(self._level-1), 10**self._level))
yield self._cache[self._nth-1]
self._nth += 1
def __next__(self):
return next(self.__iter__())
def get_nth_digit(self, nth:int) -> int :
while True:
if nth > len(self._cache):
self._level += 1
self._cache += "".join(str(i) for i in range(10**(self._level-1), 10**self._level))
else:
return int(self._cache[nth-1])
@timer
def main_longstring() -> None:
gen = ChampernownesConstant()
ziel = [1,10,100,1000,10000,100000,1000000]
res = 1
for i in ziel:
res *= gen.get_nth_digit(i)
print(res)
def length_numbers(k:int) -> int :
"""计算前k位数的总位数"""
if k == 0:
return 0
return (10**k * (9*k - 1) + 1) // 9
def get_nth_digit(nth:int) -> int :
if nth < 0 :
raise ValueError("nth must be non-negative")
level = 1
while length_numbers(level) < nth :
level += 1
# 计算在k位数中的偏移量
offset = nth - length_numbers(level-1) # 在k位数中的第几个数字
num_index = (offset - 1) // level # 第几个k位数从0开始
num = 10**(level-1) + num_index # 具体的数字
digit_index = (offset - 1) % level # 在数字中的位置
return int(str(num)[digit_index])
@timer
def main_quick() -> None :
ziel = [1,10,100,1000,10000,100000,1000000]
res = 1
for i in ziel:
res *= get_nth_digit(i)
print(res)
if __name__ == "__main__":
main_longstring()
main_quick()