Problem 26 : Reciprocal cycles
A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given:
1/2 = 0.5
1/3 = 0.(3)
1/4 = 0.25
1/5 = 0.2
1/6 = 0.1(6)
1/7 = 0.(142857)
1/8 = 0.125
1/9 = 0.(1)
1/10 = 0.1
Where 0.1(6) means 0.166666…, and has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit recurring cycle.
Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.
C++ source code
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
// #define UNIT_TEST
class PE0026
{
private:
static const int MAX_DIGITS = 1000;
bool checkRecurringCycle(vector<int>digitsVector, int start, int recurring_cycle);
int getDigitsRecurringCycle(int denominator);
public:
int getValueOfdContainingLongestRecurringCycle();
};
bool PE0026::checkRecurringCycle(vector<int>digitsVector, int start, int recurring_cycle)
{
int recurring_cycle_times = 1;
bool found = true;
for (int i=start; i-recurring_cycle> 0 && recurring_cycle_times<10; i--)
{
if (digitsVector[i] != digitsVector[i-recurring_cycle])
{
found = false;
}
else
{
recurring_cycle_times ++;
}
}
return found;
}
int PE0026::getDigitsRecurringCycle(int denominator)
{
vector<int>digitsVector;
int nominator = 1;
int numOfDigits = 1;
// bool foundRecurringCycle = false;;
int recurring_cycle = 0;
while(nominator> 0 && numOfDigits<=MAX_DIGITS)
{
nominator *= 10;
digitsVector.push_back(nominator/denominator);
nominator = nominator%denominator;
numOfDigits++;
}
// 1/d must contains the recurring cycle in its decimal fraction part.
if (numOfDigits == MAX_DIGITS+1)
{
for(int i=MAX_DIGITS-1, j=i-1; j > 0; j--)
{
if (digitsVector[i] == digitsVector[j])
{
if (true == checkRecurringCycle(digitsVector, i, i-j))
{
// foundRecurringCycle = true;
recurring_cycle = i-j;
break;
}
}
}
}
return recurring_cycle;
}
int PE0026::getValueOfdContainingLongestRecurringCycle()
{
int longest_recurring_cycle = 0;
int recurring_cycle;
int d;
for(int n=2; n<MAX_DIGITS; n++)
{
recurring_cycle = getDigitsRecurringCycle(n);
if (recurring_cycle > longest_recurring_cycle)
{
longest_recurring_cycle = recurring_cycle;
d = n;
}
}
#ifdef UNIT_TEST
cout << "1/" << d << " contains the longest recurring cycle " ;
cout << longest_recurring_cycle << " in its decimal fraction part." << endl;
#endif
return d;
}
int main()
{
PE0026 pe0026;
cout << "1/" << pe0026.getValueOfdContainingLongestRecurringCycle() ;
cout << " contains the longest recurring cycle in its decimal fraction ";
cout << "part" << endl;
return 0;
}
Python source code (I)
max_digitis = 1000
def checkRecurringCycle(digitsList, start, recurring_cycle):
recurring_cycle_times = 1
found = True
for i in range(start, recurring_cycle, -1):
if recurring_cycle_times >= 10:
break
if digitsList[i] != digitsList[i-recurring_cycle]:
found = False
else:
recurring_cycle_times += 1
return found;
def getDigitsRecurringCycle(denominator):
digitsList = []
nominator, numOfDigits, recurring_cycle = 1, 1, 1
while nominator> 0 and numOfDigits<=max_digitis:
nominator *= 10
digitsList += [ nominator/denominator ]
nominator = nominator % denominator
numOfDigits += 1
# 1/d must contains the recurring cycle in its decimal fraction part.
if numOfDigits == max_digitis+1:
i = max_digitis-1
for j in range(i-1, 0, -1):
if digitsList[i] == digitsList[j]:
if True == checkRecurringCycle(digitsList, i, i-j):
recurring_cycle = i-j;
break
return recurring_cycle
def getValueOfdContainingLongestRecurringCycle():
longest_recurring_cycle = 0
for n in range(2, max_digitis):
recurring_cycle = getDigitsRecurringCycle(n)
if recurring_cycle > longest_recurring_cycle:
longest_recurring_cycle = recurring_cycle
d = n
#print("1/",d,"contains the longest recurring cycle ", end=' ')
#print(longest_recurring_cycle," in its decimal fraction part.")
return d
def main():
print('1/',getValueOfdContainingLongestRecurringCycle(),end=' ')
print('contains the longest recurring cycle in its decimal fraction part')
if __name__ == '__main__':
main()
Python source code (II)
# This is a useful application of Fermat’s little theorem that says:
# 1/d has a cycle of n digits if (10^n − 1) mod d = 0 for prime d.
# This is called a full reptend prime.
# Full reptend prime: https://en.wikipedia.org/wiki/Full_reptend_prime
def createPrimeSieve(n):
""" create prime sieve """
sieve = [True] * n
sieve[0] = sieve[1] = False
for i in range(2, int(n**0.5)+1):
if True == sieve[i]:
for j in range(i*i, n, i):
sieve[j] = False
return [i for i in range(1, n) if sieve[i]]
def unitFraction(n):
if n < 8:
return 3
for d in createPrimeSieve(n)[::-1]:
period = 1
while (pow(10, period)-1) % d != 0: # while pow(10, period) % d != 1:
period += 1
if d-1 == period:
return d
def main():
N = int(input('The longest recurring cycle for 1/d where d <'))
print("is d =", unitFraction(N))
if __name__ == '__main__':
main()