Reputation: 17478
I got an interview and the question is how to get the length of repeating decimal?
For example
1/3=0.3333..., it returns 1,
5/7=0.7142857142857143, it returns 6, since 714285 is the repeating decimal.
1/15=0.066666666666666, it returns 1.
17/150=0.11333333333333333, it returns 1. since 3 is the repeating decimal.
And I have tried to write a code
def solution(a, b):
n = a % b
if n == 0:
return 0
mem = []
n *= 10
while True:
n = n % b
if n == 0:
return 0
if n in mem:
i = mem.index(n)
return len(mem[i:])
else:
mem.append(n)
n *= 10
However, my code can't pass all tests. And it's time complexity is O(n*logn). How can I improve that and make its time complexity O(n)?
Upvotes: 2
Views: 1135
Reputation: 1
Based on this rule which I found from Wikipedia: Fractions with prime denominators Main article: Reciprocals of primes A fraction in lowest terms with a prime denominator other than 2 or 5 (i.e. coprime to 10) always produces a repeating decimal. The length of the repetend (period of the repeating decimal segment) of 1 / p is equal to the order of 10 modulo p. If 10 is a primitive root modulo p, then the repetend length is equal to p − 1; if not, then the repetend length is a factor of p − 1. This result can be deduced from Fermat's little theorem, which states that 10p−1 ≡ 1 (mod p).
The base-10 digital root of the repetend of the reciprocal of any prime number greater than 5 is 9.[8]
If the repetend length of 1 / p for prime p is equal to p − 1 then the repetend, expressed as an integer, is called a cyclic number.
Here is my code that helps us get the repetend length:
def rep_length(n):
n=abs(n)
quotient_list=[]
if prime_factorization(n) in list([[2],[5]]) or n==1 or prime_factorization(n)==[2,5]:
return 0
#This is the case because only denominators that are powers of 2 or 5 have no repetend length because they don't repeat.
else: #1 as the denominator has no repetend length either.
n2=max([i for i in factorization(n) if i%2==1 and i%5!=0]) #These are all odd numbers not divisible by 5.
Even numbers that #are not exponents of 2 have repetend lengths because they have odd numbers not divisible by 5 as factors. num=1 remainder_list=[]
while 1 not in remainder_list:
num*=10
remainder_list.append(num%n2)
quotient_list.append(num//n2)
return len(remainder_list)
Here is the link to this: https://en.wikipedia.org/wiki/Repeating_decimal#:~:text=A%20fraction%20in%20lowest%20terms,is%20called%20a%20cyclic%20number.
Upvotes: -1
Reputation: 5954
Probably the proper way is to follow the math stack exchange link suggested by @Henry. But concerning your code here's my optimized version of it. The key point here is to use dictionary instead of array - the in
operation is much faster in this case.
def solution(a, b):
n = a % b
if n == 0:
return 0
mem = {}
n *= 10
pos = 0
while True:
pos += 1
n = n % b
if n == 0:
return 0
if n in mem:
i = mem[n]
return pos - i
else:
mem[n] = pos
n *= 10
On my computer for 29/39916801 this code finishes calculations in several seconds.
Upvotes: 3