Problem 55 : Lychrel numbers
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.
C++ 代码
#include <iostream>
#include <vector>
#include <cassert>
using namespace std;
class PE0055
{
public:
bool checkPalindromeNumber(int number, int iteration);
int getNumOfLychrelNumbers(int max);
private:
vector<int> getDigits(int number);
vector<int> reverseAndAddDigits(vector<int>& num_digits_vec);
bool checkLychrelNumber(int number, int max_iterations);
bool checkPalindrome(vector<int>digits_vec);
};
vector<int> PE0055::getDigits(int number)
{
vector<int> num_digit_vec;
while(number> 0)
{
num_digit_vec.push_back(number%10);
number /= 10;
}
return num_digit_vec;
}
vector<int> PE0055::reverseAndAddDigits(vector<int>& num_digits_vec)
{
vector<int> reverse_num_digits_vec;
reverse_num_digits_vec.assign(num_digits_vec.rbegin(), num_digits_vec.rend());
int size = num_digits_vec.size();
vector<int> sum_digits_vec(size);
int decade_flag = 0;
for(int i=0; i<size; i++)
{
sum_digits_vec[i] += num_digits_vec[i] + reverse_num_digits_vec[i];
decade_flag = sum_digits_vec[i]/10;
sum_digits_vec[i] %= 10;
if (i+1<size)
{
sum_digits_vec[i+1] += decade_flag;
}
}
if (decade_flag == 1)
{
sum_digits_vec.push_back(1);
}
return sum_digits_vec;
}
bool PE0055::checkPalindrome(vector<int> digits_vec)
{
int size=digits_vec.size();
for(int i = 0; i<size/2; i++)
{
if(digits_vec[i] != digits_vec[size-1-i])
{
return false;
}
}
return true;
}
bool PE0055::checkPalindromeNumber(int number, int iteration)
{
vector<int> num_digits_vec;
vector<int> sum_digits_vec;
num_digits_vec = getDigits(number);
for (int n=1; n<=iteration; n++)
{
sum_digits_vec = reverseAndAddDigits(num_digits_vec);
if (true == checkPalindrome(sum_digits_vec))
{
return true;
}
num_digits_vec = sum_digits_vec;
}
return false;
}
bool PE0055::checkLychrelNumber(int number, int max_iterations=50)
{
vector<int> num_digits_vec;
vector<int> sum_digits_vec;
num_digits_vec = getDigits(number);
for (int iteration=1; iteration<=max_iterations; iteration++)
{
sum_digits_vec = reverseAndAddDigits(num_digits_vec);
if (true == checkPalindrome(sum_digits_vec))
{
return false;
}
num_digits_vec = sum_digits_vec;
}
return true;
}
int PE0055::getNumOfLychrelNumbers(int max)
{
int NumOfLychrel = 0;
for (int n=1; n<max; n++)
{
if(true == checkLychrelNumber(n))
{
NumOfLychrel++;
}
}
return NumOfLychrel;
}
int main()
{
PE0055 pe0055;
assert(true == pe0055.checkPalindromeNumber(349, 3));
cout << "There are " << pe0055.getNumOfLychrelNumbers(10000);
cout << " Lychrel numbers below ten-thousand" << endl;
return 0;
}
Python 代码
def checkPalindrome(product):
return str(product) == str(product)[::-1]
def checkPalindromeNumber(number, iterations):
for iteration in range(1, iterations+1):
reverse_number = int(str(number)[::-1])
number += reverse_number
if True == checkPalindrome(number):
return True
return False
def checkLychrelNumber(number, iterations=50):
for iteration in range(1, iterations+1):
reverse_number = int(str(number)[::-1])
number += reverse_number
if True == checkPalindrome(number):
return False
return True
def getNumOfLychrelNumbers(max):
return sum (True == checkLychrelNumber(n) for n in range (1, max+1))
def main():
assert True == checkPalindromeNumber(349, 3)
print("There are", getNumOfLychrelNumbers(10000),end='');
print(" Lychrel numbers below ten-thousand")
if __name__ == '__main__':
main()