I was trying to solve project Euler problem 4 which is:
A palindromic number reads the same both ways. The largest palindrome made from the product of tw
This method is significantly faster than previous methods. It starts by evaluating 999 * 999. It is an implementation of the method proposed in Puzzled over palindromic product problem
We would like to try larger products before smaller products, so next try 998 * 998, with the outer loop decreasing by one each time. In the inner loop, take the outer limit number to create (n+y)(n-y) (which is always less than n^2), iterating over y until one of the factors is too large or too small.
From https://pthree.org/2007/09/15/largest-palindromic-number-in-python/, one of the factors must be a multiple of 11. Check to see if one of the factors is a multiple of 11 and that the product is greater than the previously found (or initial) palindromic number.
Once these tests are satisfied, see if the product is a palindrome.
Once a palindrome is found, we can raise the limit on the outer loop to the square root of the palindrome, since that is the minimum value that could possibly be an answer.
This algorithm found the answer in only 475 comparisons. This is far better than 810,000 proposed by the simple methods, or even 405450.
Can anyone propose a faster method?
Longest palindromes:
Max factor Max Palindrome
9999 99000099
99999 9966006699
999999 999000000999
9999999 99956644665999
99999999 9999000000009999
999999999 999900665566009999
public class LargestPalindromicNumberInRange {
private final long lowerLimit;
private final long upperLimit;
private long largestPalindrome;
private long largestFirstFactor;
private long largestSecondFactor;
private long loopCount;
private long answerCount;
public static void main(String[] args) {
long lowerLimit = 1000;
long upperLimit = 9999;
LargestPalindromicNumberInRange palindromicNumbers =
new LargestPalindromicNumberInRange(lowerLimit, upperLimit);
palindromicNumbers.TopDown();
}
private LargestPalindromicNumberInRange(long lowerLimit, long upperLimit){
this.lowerLimit = lowerLimit;
this.upperLimit = upperLimit;
}
private void TopDown() {
loopCount = 0;
answerCount = 0;
largestPalindrome = lowerLimit * lowerLimit;
long initialLargestPalindrome = largestPalindrome;
long lowerFactorLimit = lowerLimit;
for (long limit = upperLimit; limit > lowerFactorLimit; limit--){
for (long firstFactorValue = limit; firstFactorValue >= limit - 1; firstFactorValue--) {
long firstFactor = firstFactorValue;
long secondFactor = limit;
while(secondFactor <= upperLimit && firstFactor >= lowerLimit){
if (firstFactor % 11 == 0 || secondFactor % 11 == 0) {
long product = firstFactor * secondFactor;
if (product < largestPalindrome) { break; }
loopCount++;
if (IsPalindromic(product)) {
// System.out.print("Answer: " + product + "\n");
answerCount++;
largestPalindrome = product;
largestFirstFactor = firstFactor;
largestSecondFactor = secondFactor;
lowerFactorLimit = (long) Math.sqrt(largestPalindrome);
break;
}
}
firstFactor--;
secondFactor++;
}
}
System.out.print("Answer: " + largestPalindrome + "\n");
System.out.print("Factor1: " + largestFirstFactor + "\n");
System.out.print("Factor2: " + largestSecondFactor + "\n");
System.out.print("Loop count: " + loopCount + "\n");
System.out.print("Answer count: " + answerCount + "\n");
}
private boolean IsPalindromic(Long x) {
String forwardString = x.toString();
StringBuilder builder = new StringBuilder();
builder.append(forwardString);
builder = builder.reverse();
String reverseString = builder.toString();
return forwardString.equals(reverseString);
}
}