DEV Community

Peter Kim Frank
Peter Kim Frank

Posted on

Project Euler #4 - Largest Palindrome Product

I'm bumping a "series" that I started last year, where we collectively work on problems from Project Euler.

This is Problem 4, finding the largest palindrome product.

A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 Γ— 99.

Find the largest palindrome made from the product of two 3-digit numbers.

Latest comments (36)

Collapse
 
rossman profile image
Rossman

C#

    internal class Task4
    {
        public static string Reverse(string s)
        {
            char[] charArray = s.ToCharArray();
            Array.Reverse(charArray);
            return new string(charArray);
        }

        private bool IsPalindrome(int number) 
        {
            string strNumber = number.ToString();
            string reversedStrNumber = Reverse(strNumber);
            return strNumber == reversedStrNumber;
        }
        public Task4() 
        {
            int maxPalindrome = int.MinValue;
            for(int i = 999; i > 99; i--) 
            {
                for (int j = 999; j > 99; j--)
                {
                    int result = i * j;
                    if (result > maxPalindrome && IsPalindrome(result))
                        maxPalindrome = result;
                }
            }
            Console.WriteLine(maxPalindrome);
        }
    }
Enter fullscreen mode Exit fullscreen mode
Collapse
 
starchcode profile image
starchcode

here is my result using JS. avoided any use of methods. Also not a master in mathematics but here it is

Collapse
 
handsomespydie profile image
SpyDie • Edited

A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 Γ— 99.

Find the largest palindrome made from the product of two 3-digit numbers.

This is the easiest way and logical too..

list = []

for i in range(901,1000):
    for j in range(901,1000):
        prod = i*j
        if str(prod) == str(prod)[::-1]:
            list.append(prod)

    i += 1
    j += 1

list.sort()

print(list[-1])
Collapse
 
shyam1110 profile image
shyam1110

Complete Solution..!!! for Euler 004

void solve()
{
fast;
ll n,largepalin=0;
cin>>n;
for(ll i=999;i>=100;i--)
{
for(ll j=999;j>=100;j--)
{
if((i*j)%11==0 && palin(i*j) && (i*j)<n) largepalin=max(i*j,largepalin);
}
}
cout<<largepalin<<endl;
return;
}

Collapse
 
seyedmahmoudbayazid profile image
Mahmoud Bayazid

First observation is that the number must be between 100^2 and 999^2 or in the range of [10000, 998001].

As the majority of numbers has 6 digits and we're looking for the largest, we ignore 5 digits numbers.

Based on this, we can construct a palindromic number as:

'abccba' =100000a+10000b+1000c+100c+10b+a

=100001a+10010b+1100c

=11(9091a+910b+100c) = p.q

This equation shows us, that either p or q, but not both must have a factor of 11!!!

def palindrome_number(x,y):

my_list =[]

for i in range(x,y):
    for j in range(x,y):
        num = i * j
        if num % 11 ==0 and str(num) == str(num)[::-1]:
            my_list.append(num)
            my_list.sort()

print(my_list[-1])
Collapse
 
shyam1110 profile image
shyam1110

void solve()
{
fast;
ll n,largepalin=0;
cin>>n;
for(ll i=999;i>=100;i--)
{
for(ll j=999;j>=100;j--)
{
if((i*j)%11==0 && palin(i*j) && (i*j)<n) largepalin=max(i*j,largepalin);
}
}
cout<<largepalin<<endl;
return;
}

Collapse
 
prabh profile image
Prabhjot Singh Rana • Edited

Solution in Python:

x = 0   # assuming number is Xnnnnn  1st digit
y = 0   # assuming number is nYnnnn  2nd digit
z = 0   # assuming number is nnZnnn  3rd digit

num = 999  #highest 3 digit number

palidromefound = False

highestnum = num * num

while str(highestnum) != str(highestnum)[::-1]:

    z = int(highestnum / 1000)
    z = z%10

    y = int(highestnum / 10000)
    y = y%10

    x = int(highestnum / 100000)
    x = x%10

    if z != 0 and y != 0:
        z = z-1

    # first time find the highest palidrom

    highestnum = (x*100000 + y*10000 + z*1000 + z*100 + y*10 + x)


while palidromefound == False:

    if str(highestnum) == str(highestnum)[::-1]:
        while num > 99:

            if (highestnum % num) == 0 and (highestnum / num) < 999 and (highestnum / num) > 99:
                palidromefound = True
                print(f'Highest Palidrom: {highestnum} num1: {num} and num2: {int(highestnum / num)}')
                break
            num = num -1

        else:

            num = 999

            # below are the palidromes.. the value of z is the 3rd digit, it comes from the above logic
            # when the first highest palidrom is found, but if it not a multiple of two three digit numbers
            # then the next highest palidrome is obtained:
            #
            # 992299 - 1100 = 991199  >> when z != 0
            # 991199 - 1100 = 990099  >> when z != 0
            # 990099 - 110  = 989989  >> when z == 0
            # 989989 - 1100 = 988889  >> when z != 0 


            if z == 0:
                highestnum = highestnum -110
                z = 9
            else:
                highestnum = highestnum -1100
                z = z-1
Collapse
 
shahidcodes profile image
Shahid Kamal Khan

Here is freeCodeCamp version of it


function largestPalindromeProduct(n) {
  // Good luck!
  const isPalindrom = n => {
    return String(n).split("").reverse().join("") === String(n);
  }
  let largestPalindrome = 0;
  const lowerBound = Number(`1${Array.from({length:n}).join(0)}`);
  const upperBound= Number(`${Array.from({length: n+1}).join(9)}`);
  console.log({upperBound, lowerBound})
  for(var i=lowerBound; i<=upperBound; i++) {
    for(var j=lowerBound; j<=upperBound; j++) {
    const product = i*j;
      if(isPalindrom(product) && product > largestPalindrome ) {
        console.log(i, j, product, largestPalindrome)
        largestPalindrome = i*j;
      }
    }
  }
  return largestPalindrome;
}

largestPalindromeProduct(2);
Collapse
 
vienpham2019 profile image
vienpham2019

This is my solution in Javascript

function largestPalindromeProduct(n) {
let num = "1"
let lNumber = 0
for(let i = 0; i < n; i++){
num = ${num}0
}
num = parseInt(num)
let rangeNum = num.toString().replace("0","")
lNumberLoop:
for(let i = num; i > 0 ; i--){
for(let j = i; j > i - rangeNum; j --){
let number = (i * j)
let revN = parseInt(number.toString().split("").reverse().join(""))
if(number === revN && revN.toString().length % 2 === 0){
lNumber = number
break lNumberLoop
}
}
}
return lNumber
}

console.log(largestPalindromeProduct(2));

Collapse
 
ib250 profile image
Ismail Bello

a lazy c++ solution :)

auto larget_palindrome_product(size_t n_digits) -> size_t {

    const auto is_palidrome = [](size_t x) -> bool {
        const auto as_string = std::to_string(x);
        auto fst = as_string.begin();
        auto lst = as_string.rbegin();
        for (; fst != as_string.end(); fst++, lst++)
            if (*fst != *lst) return false;
        return true;
    };

    size_t result = 0;
    const auto lower_bound = std::pow(10, n_digits - 1);
    const auto upper_bound = std::pow(10, n_digits) - 1;

    for (size_t fst = lower_bound; fst <= upper_bound; fst++) {
        for (size_t snd = fst; snd <= upper_bound; snd++) {
            if (auto n = fst * snd;
                is_palidrome(n) && n > result) {
                result = fst * snd;
            }
        }
    }

    return result;
}
Collapse
 
khouloudzaiter profile image
khouloudzaiter

Written in Java!

public class Problem4 {
    public static boolean isPalindrome(long val) {
            boolean isPalindrome = true;
            String str = Long.toString(val);
            int len = str.length();
            int i = 0;
            while (isPalindrome && i <= (len-1)/2){
                isPalindrome = str.charAt(i) == str.charAt(len-1-i);
                i++;
            }
            return isPalindrome;
        }

        public static void main(String[] args) {
            int i = 999;
            long largest = 1;
            String str = "";
            long val = 1;
        while (i>=100)
        {
            int j = i;
            while (j>=100)
            {
                val = i * j;
                if(isPalindrome(val) && largest < val)
                {
                    largest = val;
                    str = i + " x " + j;
                }
                isPalindrome (val);
                j--;
            }
            i--;
        }
        System.out.println(str+ "= "+ largest);

    }
}
 
maxart2501 profile image
Massimo Artizzu

Being wrong is nothing to be ashamed of, as long as you're ready to stand corrected.

My mistake in this case is that I commented while it was very late 😴 Took note on the approach, though.

 
maxart2501 profile image
Massimo Artizzu

I'm sorry if that seemed rude, that wasn't my intention at all. I did add "granted I could understand F#" in case I was wrong.

But no, I will keep on trying to understand what's going on in other people's code even out of my comfort zone, because I'll have the chance to learn something new πŸ‘Œ

Collapse
 
maxart2501 profile image
Massimo Artizzu

This is another solution that I consider working in this particolar case (3 digits) but not actually correct (granted I could understand F# πŸ˜…). I explained it here: dev.to/maxart2501/comment/b9me

Collapse
 
maxart2501 profile image
Massimo Artizzu • Edited

Sooo... there are so many good solutions, but they all kind of look the same, so I wanted a different approach 😁

What if, instead of starting with the factors and checking if their product is a palindrome, we start with palindromes and find two 3-digit factors?

We'd start with 999999, then 998899, then 997799... You get the point. So we can start with a 3-digit number (e.g. 356)... and get a palindrome out of it (e.g. 356653), and look for factors.

My solution in JavaScript:

const digits = 3;
const upper = 10 ** digits - 1;   // 999
const lower = 10 ** (digits - 1); // 100
function palindromize(num) {
  const padded = String(num).padStart(digits,'0');
  return +(padded + padded .split('').reverse().join(''));
}

let p, b;
out: for (let a = upper; a >= lower; a--) {
  p = palindromize(a);
  for (b = Math.floor(p ** .5); p/b <= upper; b--) {
    if (p % b === 0) break out;
  }
}
console.log(p / b, b);

I've tested it with up to 7 digits and it's still basically instantaneous. Over that limit you go over Number.MAX_SAFE_INTEGER and it becomes unreliable. I didn't bother using BigInts, also because you can't get the square root out of them (you can approximate it, but it's a bother).

P.S.: yes, I've used a label in JavaScript. Sue me πŸ˜‚ (also useful if you have to break out of more than one cycle... which is usually rare).

Some comments may only be visible to logged-in visitors. Sign in to view all comments.