package testing.project;
public class PalindromeThreeDigits {
public static void main(String[] args) {
int value = 0;
for(int i = 100;i <=999;i+
We can translate the task into the language of mathematics.
For a short start, we use characters as digits:
abc * xyz = n
abc is a 3-digit number, and we deconstruct it as 100*a+10*b+c
xyz is a 3-digit number, and we deconstruct it as 100*x+10*y+z
Now we have two mathematical expressions, and can define a,b,c,x,y,z as € of {0..9}.
It is more precise to define a and x as of element from {1..9}, not {0..9}, because 097 isn't really a 3-digit number, is it?
Ok.
If we want to produce a big number, we should try to reach a 9......-Number, and since it shall be palindromic, it has to be of the pattern 9....9. If the last digit is a 9, then from
(100*a + 10*b + c) * (100*x + 10*y + z)
follows that z*c has to lead to a number, ending in digit 9 - all other calculations don't infect the last digit.
So c and z have to be from (1,3,7,9) because (1*9=9, 9*1=9, 3*3=9, 7*7=49).
Now some code (Scala):
val n = (0 to 9)
val m = n.tail // 1 to 9
val niners = Seq (1, 3, 7, 9)
val highs = for (a <- m;
b <- n;
c <- niners;
x <- m;
y <- n;
z <- niners) yield ((100*a + 10*b + c) * (100*x + 10*y + z))
Then I would sort them by size, and starting with the biggest one, test them for being palindromic. So I would omit to test small numbers for being palindromic, because that might not be so cheap.
For aesthetic reasons, I wouldn't take a (toString.reverse == toString) approach, but a recursive divide and modulo solution, but on todays machines, it doesn't make much difference, does it?
// Make a list of digits from a number:
def digitize (z: Int, nums : List[Int] = Nil) : List[Int] =
if (z == 0) nums else digitize (z/10, z%10 :: nums)
/* for 342243, test 3...==...3 and then 4224.
Fails early for 123329 */
def palindromic (nums : List[Int]) : Boolean = nums match {
case Nil => true
case x :: Nil => true
case x :: y :: Nil => x == y
case x :: xs => x == xs.last && palindromic (xs.init) }
def palindrom (z: Int) = palindromic (digitize (z))
For serious performance considerations, I would test it against a toString/reverse/equals approach. Maybe it is worse. It shall fail early, but division and modulo aren't known to be the fastest operations, and I use them to make a List from the Int. It would work for BigInt or Long with few redeclarations, and works nice with Java; could be implemented in Java but look different there.
Okay, putting the things together:
highs.filter (_ > 900000) .sortWith (_ > _) find (palindrom)
res45: Option[Int] = Some(906609)
There where 835 numbers left > 900000, and it returns pretty fast, but I guess even more brute forcing isn't much slower.
Maybe there is a much more clever way to construct the highest palindrom, instead of searching for it.
One problem is: I didn't knew before, that there is a solution > 900000.
A very different approach would be, to produce big palindromes, and deconstruct their factors.