Numerical Palindromes

Let N N be the 1500 1500 -digit string of decimal digits linked here .

Consider all substrings of N N with length strictly greater than 1. 1. Let P P be the number of these substrings that are palindromes (read the same forwards and backwards), and let L L be the largest palindromic substring (converted to an integer). Compute the remainder when P + L P + L is divided by 1000. 1000.

EDIT: The number is:

  845339512654353013973726529001291079167398839841139949030851696390946980101698124639149591440119733604468880607555560607206064491347909369911515301019367711551352591990261320383329288164577799740443242050242319267457621744807851983932903020081029321152325175250685866007841518940360280269649423980138752509028919270696197406591840726262868909999601238346887569491166411930108771076009573412594100219771074212035289275491573364890832367256854827355325731308226389028814609823679403212837077171147035094962722853937529780881806452156815760851836710785281112178566572142070924792670573967021943625926183861042230278394450084283686782710687142035589512463860007382666540574865786548090984873591052303316826223089810233823833877818493413413377572125316440837829248059997597530413074225936022537356928726861032836482495816729317138037356704312711814039586229918016418907376961773423879993723686730471541871754763457516922397978666764180907493617108196535775671577122375548642715864362660363698285254692252450789495296857844775409285832067120397741225920809730915094640238325092213217491635025536097960140990339793121105117908393671593840606430927286507282838120710540761234699189422511628632095218354056738982111107254470000373451953905544838296347383706816543780729267523585541214385956448406268928721934984154648198940685892036868554606054558448653750977153318569536525693630516086917674823412432181461884413411201293004004992015882876179775802939973661220145456423636324708339384632070192417332964444202


The answer is 755.

This section requires Javascript.
You are seeing this because something didn't load right. We suggest you, (a) try refreshing the page, (b) enabling javascript if it is disabled on your browser and, finally, (c) loading the non-javascript version of this page . We're sorry about the hassle.

9 solutions

Daniel Chiu
Dec 23, 2013

I used a brute-force strategy. I loop over all possible values of the index of the first digit of a substring, and then over all possible values of the length of the substring to grab all possible substrings. Then, I check whether each substring is a palindrome, and whether the integer value is larger than the current largest. Finally, I print P P and L L to check, along with the desired P + L P+L .

Python:

s = "845339512654353013973726529001291079167398839841139949030851696390946980101698124639149591440119733604468880607555560607206064491347909369911515301019367711551352591990261320383329288164577799740443242050242319267457621744807851983932903020081029321152325175250685866007841518940360280269649423980138752509028919270696197406591840726262868909999601238346887569491166411930108771076009573412594100219771074212035289275491573364890832367256854827355325731308226389028814609823679403212837077171147035094962722853937529780881806452156815760851836710785281112178566572142070924792670573967021943625926183861042230278394450084283686782710687142035589512463860007382666540574865786548090984873591052303316826223089810233823833877818493413413377572125316440837829248059997597530413074225936022537356928726861032836482495816729317138037356704312711814039586229918016418907376961773423879993723686730471541871754763457516922397978666764180907493617108196535775671577122375548642715864362660363698285254692252450789495296857844775409285832067120397741225920809730915094640238325092213217491635025536097960140990339793121105117908393671593840606430927286507282838120710540761234699189422511628632095218354056738982111107254470000373451953905544838296347383706816543780729267523585541214385956448406268928721934984154648198940685892036868554606054558448653750977153318569536525693630516086917674823412432181461884413411201293004004992015882876179775802939973661220145456423636324708339384632070192417332964444202"

P = 0
L = 0
for i in range(len(s)):
    for j in range(2,len(s)-i+1):
        if s[i:i+j][::-1]==s[i:i+j]:
            P+=1
            if int(s[i:i+j])>L:
                L = int(s[i:i+j])
print P,L,P+L

This prints out 332 32420502423 32420502 755 332\ 32420502423\ 32420502\boxed{755} .

The way you handled the problem is really admirable.

Lokesh Sharma - 7 years, 5 months ago

I used for loops based on the start and end. Good approach!

Michael Tang - 7 years, 5 months ago

Just curious, what was your runtime? I brute-forced it as well and ended up with a horrible runtime of about 3 minutes. Was yours much better?

Carl Denton - 7 years, 5 months ago

Log in to reply

2.105 seconds

Daniel Chiu - 7 years, 5 months ago

Log in to reply

How do you find runtime?

Lokesh Sharma - 7 years, 5 months ago

Log in to reply

@Lokesh Sharma import time and then time.clock() at the beginning. To find elapsed time at any point call time.clock() again, which will return the time since the first call to it.

Daniel Chiu - 7 years, 5 months ago

Log in to reply

@Daniel Chiu Thanks. It worked. Mine was 6.7 seconds.

Lokesh Sharma - 7 years, 5 months ago

Log in to reply

@Lokesh Sharma On re-examining my code I found the problem and managed to get it down to about 110 ms. Nice work!

Carl Denton - 7 years, 5 months ago

Log in to reply

@Carl Denton Whoa! 3 minutes to 110 ms. Would you mind pasting your re-examined code here?

Lokesh Sharma - 7 years, 5 months ago

Log in to reply

@Lokesh Sharma Sure. I did it in Java.

public class Palindrome 
{
public static void main(String[] args)
{
   long startTime =     System.currentTimeMillis();
    String input = args[0];
    int count = 0;
    String longest = "0";
            for (int subLength = 2; subLength <=  
                            input.length() ; subLength++)
        for(int pos = 0; pos <= input.length() - 
                             subLength; pos++)
        {
            if (isPalindrome(input.substring( 
                                       pos, pos + subLength)))
            {
                count++;    

if(Long.parseLong(input.substring(pos, pos + 
subLength)) > Long.parseLong(longest))
                {
                    longest = 
input.substring(pos, pos + subLength);
                }
            }
        }
    System.out.println("Count: " + count);
    System.out.println("Longest: " + longest);
    System.out.println("Remainder: " + 
(Long.parseLong(longest) + count) % 1000);
    long endTime = 
System.currentTimeMillis();
    long timeElapsed = endTime - startTime;
    System.out.println("Runtime: " + 
timeElapsed + " ms");
}
public static boolean isPalindrome(String s)
{
    boolean palindrome = true;
    for (int i = 0; i < s.length()/2; i++)
    {
        if (s.charAt(i) == s.charAt(s.length() - 
                               1 - i))
            continue;
        else
        {
            palindrome = false;
            break;
        }
    }
    return palindrome;
}
}

Carl Denton - 7 years, 5 months ago

Log in to reply

@Carl Denton Sorry, it's a bit lengthy with the margins of the comments. The problem was that in the isPalindrome(String s) method, I had previously been simply adding to the new string character by character using a "+=" operator. With strings, this creates a whole new string object, so for each character of the string I had been simply creating an entirely new object, which takes a lot of time. I revised to the above code and the runtime went to down to about 110 ms. I knew creating strings took time, but I was surprised at just how much of a difference it made!

Carl Denton - 7 years, 5 months ago

Log in to reply

@Carl Denton Hi guys,

Why is no one preferring parallel processing? Instead of going for normal loop processing, palindromes of different lengths can be found in parallel. I actually used, Java's StringBuffer reverse, which itself is heavy and along with it, I loaded the program with an ArrayList for adding palindromes. Again iterated over the ArrayList to compute the final result. Worst possible way to solve it. But the thing is, mine took about 0.65 seconds the first time itself. Started 1499 threads. I am pretty sure this could even be reduced to very less, a well informed guess gives me about 150 ms, 100 to actually solve and 50 is the thread overhead. But, if the length of the string is increased, it'd overcome the thread overhead. Is there any particular reason that no one has used Threads or parallel processing?

Abhishek Gorlagunta - 7 years, 4 months ago

+1 for compact & self explained code. took 7.108s on my computer.

Debjyoti Bhaumik - 7 years, 5 months ago

This takes under 1 sec on my machine... haven't tested exactly how much :D

import sys
import csv

f=open("data.txt",'r')
reader=csv.reader(f)
b=f.readline()
P=0
longest=""
startLongest=0
endLongest=0
longestLength=0
    def checkLength(j,k,tempLength):
    global longest,startLongest,endLongest,longestLength
    if tempLength>longestLength:
        startLongest=j
        endLongest=k
        longest=b[j:k+1]
        longestLength=tempLength
def check1(b):
    global P
    for i in range (1,1499):
        j=i-1
        k=i+1
        tempLength=1
        while j>=0 and k<=1499:
            if b[j]==b[k]:
                tempLength=tempLength+2             
                checkLength(j,k,tempLength)
                P=P+1
                j=j-1
                k=k+1
            else:
                break
def check2(b):
    global P
for i in range (0,1500):
        j=i
        k=i+1
        tempLength=0
        while j>=0 and k<=1499:
            if b[j]==b[k]:
                tempLength=tempLength+2             
                checkLength(j,k,tempLength)
                P=P+1
                j=j-1
                k=k+1
            else:
                break

check1(b)
check2(b)
print P+int(longest)%1000

Nikola Bozhinov - 7 years, 5 months ago

Lucky you, the longest palindrome is also the largest because there is only the longest palindrome!

Từ Thiện Nguyễn Văn - 7 years, 5 months ago

Log in to reply

I convert to an integer, so that shouldn't be a problem, right?

Daniel Chiu - 7 years, 5 months ago

Log in to reply

Oh, sorry! You're right! :D

Từ Thiện Nguyễn Văn - 7 years, 5 months ago
Noah Singer
Dec 30, 2013

First, we must define a Python function to check whether a number is a palindrome. We need to recognize that for a given string n u m num , if it's a palindrome with an even number of digits, n u m [ : ( l e n ( n u m ) / / 2 ) ] num[:(len(num) // 2)] must be the same as n u m [ ( l e n ( n u m ) / / 2 ) : ] [ : : 1 ] num[(len(num) // 2):][::-1] , i.e. the first half of the string is the same as the second half reversed. We also recognize that for a palindrome with an odd number of digits, we apply the same logic but simply ignore the middle digit, i.e. replace the second expression with n u m [ ( l e n ( n u m ) / / 2 + 1 ) : ] [ : : 1 ] num[(len(num) // 2 + 1):][::-1] (the syntax ::-1 means to reverse the string). Note that since any multiple of two mod two is zero and any odd number mod two is one, we end up with this definition:

def isPalindrome(num):
  return [(len(num) // 2 + len(num) % 2):][::-1]

Next, we take our string, string , and split it into substrings, using Python's concise generator syntax to find a start and end and then slice the string:

substrs = [string[start:end] for start in range(0, len(string) - 2) for end in range(start + 2, len(string) + 1)]

Finally, we write a loop to find P and L, initializing them both to zero:

for substr in substrs:
  if isPalindrome(substr):
    P += 1
      if int(substr) > L:
        L = int(substr)

We top it off by printing the value P + L P + L , mod 1000.

Forgot to mention, it takes 9 seconds to run on my system.

Noah Singer - 7 years, 5 months ago

My Python solution

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
string = open('file.txt').readline()

# Notes to self
# P = number of substrings with length > 1 that are palindromes.
# L = largest palindromic (read the same forwards and backwards) substring.
# Answer is (P + L) % 1000

from time import clock

clock()

P = 0
L = ''

for a in range(len(string) - 1):
    c = string[a]
    for b in range(1, len(string) - a):
        c += string[a + b]
        if c == c[::-1]:
            P += 1
            if b + 1 > len(L):
                L = c

print('Answer is %d\nTook %f seconds' % ((P + eval(L)) % 1000, clock()))

Oliver Welsh
Dec 26, 2013

Python solution:

#Creating the palindrome function
def is_palindrome(s):
    return s == s[::-1]

#Opening the file and storing characters into a variable
f = open('Number_Palindromes.txt', 'r')
chars = [line for line in f][0]
 #Defining variables for the loop
total = 0
largest = 0
#Loop through the starting index and substring length
for i in range(len(chars)):
    for substr_len in range(2, len(chars) - i + 1):
        #Calls palindrome function
        s = chars[i:i + substr_len]
        if is_palindrome(s):
            total += 1
            #Checks to see if it is the largest palindrome
            if int(s) > largest:
                largest = int(s)

#Print the answer and close the file
print (largest + total) % 1000
f.close()

My solution it takes around 2 secs on my computer

!/usr/bin/python3.3

string="845339512654353013973726529001291079167398839841139949030851696390946980101698124639149591440119733604468880607555560607206064491347909369911515301019367711551352591990261320383329288164577799740443242050242319267457621744807851983932903020081029321152325175250685866007841518940360280269649423980138752509028919270696197406591840726262868909999601238346887569491166411930108771076009573412594100219771074212035289275491573364890832367256854827355325731308226389028814609823679403212837077171147035094962722853937529780881806452156815760851836710785281112178566572142070924792670573967021943625926183861042230278394450084283686782710687142035589512463860007382666540574865786548090984873591052303316826223089810233823833877818493413413377572125316440837829248059997597530413074225936022537356928726861032836482495816729317138037356704312711814039586229918016418907376961773423879993723686730471541871754763457516922397978666764180907493617108196535775671577122375548642715864362660363698285254692252450789495296857844775409285832067120397741225920809730915094640238325092213217491635025536097960140990339793121105117908393671593840606430927286507282838120710540761234699189422511628632095218354056738982111107254470000373451953905544838296347383706816543780729267523585541214385956448406268928721934984154648198940685892036868554606054558448653750977153318569536525693630516086917674823412432181461884413411201293004004992015882876179775802939973661220145456423636324708339384632070192417332964444202"

ln = len(string) - 1 N = 0 Lstart = 0 Ldistance = 0 for i in range(ln): #search for a end end = ln while end > i : if string[i] == string[end]: #Got an end #To check if it is symetric ni = i ne = end while ni < ne: if string[ni] != string[ne]: break ni += 1 ne -= 1 if ne <= ni: #Got a symetric N += 1 distance = end - i + 1 if distance > Ldistance: Ldistance = distance Lstart = i end -= 1 s = int(string[Lstart:Lstart + Ldistance]) + N print( s % 1000 )

Debjyoti Bhaumik - 7 years, 5 months ago
Bùi Kiên
Feb 24, 2014

My solution uses Hash algorithm and runtime is less than 0.1s. The input string can be written as s 1 s 2 . . . s i . . . s j . . . s n s_1 s_2 ... s_i ... s_j ... s_n .

Let's consider substring X = s i . . . s j X = s_i ... s_j . X X will be a palindrome if value of X X is equal to value of reverse string of X X (both in decimal).

Hash value of forward string X is defined as: H 1 = ( s i . 1 0 i + s i + 1 . 1 0 i + 1 + . . . + s j . 1 0 j ) % B A S E H_1 = (s_i . 10^i + s_{i+1}.10^{i+1} + ... + s_j .10^j) \% BASE

and Hash value of reverse string of X is H 2 = ( s j . 1 0 n j + 1 + s i + 1 . 1 0 n j + 2 + . . . + s i . 1 0 n i + 1 ) % B A S E H_2 = (s_j . 10^{n-j+1} + s_{i+1}.10^{n-j+2} + ... + s_i .10^{n-i+1}) \% BASE

where B A S E BASE is a big prime number, for example 1000000009 1000 000 009 .

We can conclude that X = = r e v e r v e ( X ) X == reverve(X) if H 1 . 1 0 n i = = H 2 . 1 0 j 1 H_1 . 10^{n-i} == H_2 . 10^{j-1} . The probability that above condition becomes wrong is too small, because B A S E BASE is a big prime number.

The complexity of calculating Hash value for each substring X can be O ( 1 ) O(1) by using three arrays in preprocessing step: P[i] is the power of 10 10 , a[i] is the Hash value of substring s 1 . . . s i s_1 ... s_i and b[i] is the Hash value (in reverse) of substring s [ i ] . . . s [ n ] s[i] ... s[n] .

Here is my code in short (sorry because I don't know how to insert code in the post):

n = length of(s);

ans = 0;

FOR(i,1,n) FOR(j,i+1,n) {

sum1 = (a[j]-a[i-1]+MOD)*POW[n-i]; sum1 %= MOD;

sum2 = (b[i]-b[j+1]+MOD)*POW[j-1]; sum2 %= MOD;

if(sum1 == sum2) {

 string tmp = ""; 
 FOR(k,i,j) tmp += s[k];
 cout << tmp << endl; /// it's too easy to find the longest palindrome  
 ans++;
}

} cout << ans << endl;

Isaí Vázquez
Jan 4, 2014

Simple brute force solution...

with open("big_number.txt") as problem:
    number = problem.read()    

palindromes = []    

i = 0
for digit in number:
    candidate = digit
    for c in number[i+1:]:
        candidate += c
        if candidate == candidate[::-1]:
            palindromes.append(int(candidate))    

    i+=1    


print((max(palindromes)+len(palindromes))%1000)
Ashish Awaghad
Jan 4, 2014

import java.util.Stack;

public class NumericalPalindromes {

public static void main(String[] args) {
    // TODO Auto-generated method stub

    String bigStr = "845339512654353013973726529001291079167398839841139949030851696390946980101698124639149591440119733604468880607555560607206064491347909369911515301019367711551352591990261320383329288164577799740443242050242319267457621744807851983932903020081029321152325175250685866007841518940360280269649423980138752509028919270696197406591840726262868909999601238346887569491166411930108771076009573412594100219771074212035289275491573364890832367256854827355325731308226389028814609823679403212837077171147035094962722853937529780881806452156815760851836710785281112178566572142070924792670573967021943625926183861042230278394450084283686782710687142035589512463860007382666540574865786548090984873591052303316826223089810233823833877818493413413377572125316440837829248059997597530413074225936022537356928726861032836482495816729317138037356704312711814039586229918016418907376961773423879993723686730471541871754763457516922397978666764180907493617108196535775671577122375548642715864362660363698285254692252450789495296857844775409285832067120397741225920809730915094640238325092213217491635025536097960140990339793121105117908393671593840606430927286507282838120710540761234699189422511628632095218354056738982111107254470000373451953905544838296347383706816543780729267523585541214385956448406268928721934984154648198940685892036868554606054558448653750977153318569536525693630516086917674823412432181461884413411201293004004992015882876179775802939973661220145456423636324708339384632070192417332964444202";

    Stack<Character> stack = new Stack<Character>();

    int count = 0, maxLength = 0;
    for(int i=0;i<bigStr.length();i++) {
        Character c = Character.valueOf(bigStr.charAt(i));
        Character c1 = null;
        if(i!=bigStr.length()-1) 
            c1 = Character.valueOf(bigStr.charAt(i+1));

        boolean isEven = false;
        boolean isOdd = false;
        if(!stack.isEmpty() && stack.peek().charValue() == c.charValue()) {
            isEven = true;
        }

        if(!stack.isEmpty() && c1!=null && c1.charValue() == stack.peek().charValue()) {
            isOdd = true;
        }

        if(isEven) {
            count ++;
            Stack<Character> tmpStack = new Stack<Character>();
            int j = i+1;
            int length = 2;
            while(true) {
                tmpStack.push(stack.pop());
                if(j>=bigStr.length()) break;

                if(stack.isEmpty()) break;

                if(bigStr.charAt(j) != stack.peek().charValue())
                    break;
                length += 2;
                count ++;
                j++;
            }

            while(!tmpStack.isEmpty()) {
                stack.push(tmpStack.pop());
            }

            if (length > maxLength) {
                int beginIndex = i - (j-1-i);
                beginIndex--;
                String palindromeString = bigStr.substring(beginIndex, j);
                System.out.println(palindromeString);
                maxLength = length;
            }
        }
        if(isOdd) {
            count ++;
            Stack<Character> tmpStack = new Stack<Character>();
            int j = i+2;
            int length = 3;

            while(true) {
                tmpStack.push(stack.pop());
                if(j>=bigStr.length()) break;

                if(stack.isEmpty()) break;

                if(bigStr.charAt(j) != stack.peek().charValue())
                    break;
                length += 2;
                count ++;
                j++;
            }

            while(!tmpStack.isEmpty()) {
                stack.push(tmpStack.pop());
            }

            if (length > maxLength) {
                maxLength = length;
                int beginIndex = i - (j-1-i);
                String palindromeString = bigStr.substring(beginIndex, j);
                System.out.println(palindromeString);
            }
        }

        stack.push(Character.valueOf(bigStr.charAt(i)));
    }

    System.out.println("Count: " + count);
}

}

Steve Guo
Dec 30, 2013

I'm just starting to learn Python, so forgive me for any beginner mistakes I might have made. Constructive criticism or suggestions are welcome.

list=[]
num='whatever the number is, paste it here'
for startpoint in range(0,1499):
    for endpoint in range(startpoint+1, 1500):
        sub=num[startpoint:endpoint+1]
        reverse=sub[::-1]
        if(sub==reverse):
            list.append(int(sub))
print(max(list)+len(list))

The output is 32420502 755 32420502\boxed{755} .

Lokesh Sharma
Dec 24, 2013

Python Sol:

s = open('Number_Palindromes.txt', 'r')
s = s.read()

def isPalindrome(num):
    if num == num[::-1]:
        return True
    return False

def Pal(l):
    pals = []
    for i in range(len(s) - (l - 1)):
        if isPalindrome(s[i: i + l]):
            pals.append(s[i: i + l])
    return pals

bestLen = 0
for leng in range(2, 1501):
    if len(Pal(leng)) > 0:
        bestLen = leng
print Pal(bestLen)  # This is P

allPals = []
for leng in range(2, 100):
    for i in Pal(leng):
        allPals.append(i)
print len(allPals)   # This is L

guys can y tell wats wrong in dis code ?? :)

include <stdio.h>

include <pthread.h>

include <stdlib.h>

int max;

int pallcheck(char a[2000]){

int i=0,j;




while (a[i]>0) {
    i++;

}
j=--i;
while (j) {



    if (a[i-j]!=a[j]) {
        return 0;
    }
    j--;
}


if (atoi(a)>max) {
    max=atoi(a);
}

if (atoi(a)){ return 1;}
else return 0;

}

int main(){

int i,j,k=0,c=0,flag;
char a[2000]={"845339512654353013973726529001291079167398839841139949030851696390946980101698124639149591440119733604468880607555560607206064491347909369911515301019367711551352591990261320383329288164577799740443242050242319267457621744807851983932903020081029321152325175250685866007841518940360280269649423980138752509028919270696197406591840726262868909999601238346887569491166411930108771076009573412594100219771074212035289275491573364890832367256854827355325731308226389028814609823679403212837077171147035094962722853937529780881806452156815760851836710785281112178566572142070924792670573967021943625926183861042230278394450084283686782710687142035589512463860007382666540574865786548090984873591052303316826223089810233823833877818493413413377572125316440837829248059997597530413074225936022537356928726861032836482495816729317138037356704312711814039586229918016418907376961773423879993723686730471541871754763457516922397978666764180907493617108196535775671577122375548642715864362660363698285254692252450789495296857844775409285832067120397741225920809730915094640238325092213217491635025536097960140990339793121105117908393671593840606430927286507282838120710540761234699189422511628632095218354056738982111107254470000373451953905544838296347383706816543780729267523585541214385956448406268928721934984154648198940685892036868554606054558448653750977153318569536525693630516086917674823412432181461884413411201293004004992015882876179775802939973661220145456423636324708339384632070192417332964444202"};

char temp;

while (a[k]>0) {
    k++;

}


printf(" k=%d\n  ",k);
for (i=0; i<k-1; i++) {


    for (j=i+1; j<k; j++) {

        flag=1;
        if (a[i]==a[j]&&a[i]!='0') {
            temp=a[j+1];

            a[j+1]=0;
            if (pallcheck(&a[i])) {
                c++;

            }
            a[j+1]=temp;
        }
    }


}

printf(" \nc=%d max=%d\n ",c,max);
printf("%d",((c+max)%1000));

}

Vishnu Swaroop - 7 years, 5 months ago

Log in to reply

got it

code is corrcet should have taken double but took int :P

Vishnu Swaroop - 7 years, 5 months ago

0 pending reports

×

Problem Loading...

Note Loading...

Set Loading...