Find next largest palindrome number - c++

I wrote the following program to find the nearest largest palindrome for each of the entered numbers. The first line gives input of how many integers are to be entered.
My problem is I've tried with test cases on geekforgeeks and spojtoolkit (also random numbers whose nearest palindrome I know) and am getting the right answer. SPOJ however says wrong answer. Can anyone suggest cases where my code may not work or possible corrections in my code.
using namespace std;
void evenmirror(char g[1000000],int n)
{
int k=n/2;
for(int i=n/2-1;i>=0;i--)
{
g[k]=g[i];
k++;
}
cout<<g;
}
void oddmirror(char g[1000000],int n)
{
int k=n/2+1;
for(int i=n/2-1;i>=0;i--)
{
g[k]=g[i]; k++;
}
cout<<g;
}
int main()
{
int n,i,j,m;
char g[1000000];
cin>>m;
for(int t=0;t<m;t++)
{
cin>>g;
n=strlen(g);
if(n==1 && g[0]!='9'){cout<<++g[0]; continue;}//single digits except9
int s=0;
int h=0;
if(g[0]=='9' && g[n-1]=='9')
{
for(i=0;i<n;i++)
{
if(g[i]=='9') {h++; }
}
if(h==n)
{
for(i=0;i<=n;i++)
{
if(i==0 || i==n) { cout<<1;}
else {cout<<0;}
}
s=1;
}
}
if(n%2==0 && s==0)
{
i=n/2-1; j=n/2;
while(g[i]==g[j] && i>0)
{
i--; j++;
if(i==0){break;}
}
//if palindrome
if(j==n-1 && g[j]==g[i])
{
if(g[n/2-1]<'9'){ g[n/2-1]++; }
else if(g[n/2]=='9'){(g[n/2-1])='0'; g[n/2-2]+=1;}
evenmirror(g,n);
}//if even string is not palindrome
else
{
if(g[i]<g[j])
{
if(g[n/2-1]<'9'){ g[n/2-1]++; }
else if(g[n/2]=='9'){ g[n/2-1]='0'; g[n/2-2]+=1;}
evenmirror(g,n);
}
else{ evenmirror(g,n); }
}
}
//if odd number string
else if(n%2!=0 && s==0)
{
i=(n/2)-1; j=(n/2)+1;
while(g[i]==g[j] && i>0)
{
i--; j++;
}
//if palindrome
if(j==n-1 && g[j]==g[i])
{
if(g[n/2]<'9'){ g[n/2]++; }
else if(g[n/2]=='9'){ g[n/2]='0'; g[n/2-1]+=1;}
oddmirror(g,n);
}//if odd not palindrome
else
{
char k=n/2+1;
if(g[i]<g[j])
{
if(g[n/2]<'9'){ g[n/2]++; }
else if(g[n/2]=='9'){(g[n/2])='0'; g[n/2-1]+=1;}
oddmirror(g,n);
}
else{ oddmirror(g,n); }
}
}
cout<<endl;
}
return 0;
}
Here is the question: http://www.spoj.com/problems/PALIN/

I didn't debug your code (you didn't ask for it and I think that it should be done by you anyway) but for the following input I got wrong answer:
Input: 9 (expected output 11)
Output: :
Good luck fixing it :)

Since this is an algorithm question, I'll try to keep it language neutral.
The simple way to find the next palindrome is to keep testing until you find one, stepping up one at a time. This is simply a loop, incrementing one at a time and testing.
The test for a palindrome is quite simple. I think you've overcomplicated it by splitting it into odd and even cases. You can either turn the number into a string and check the reverse() is the same, which is neat and tidy (because it's inside a call), but takes memory, or you can do it in place using two pointers. One pointer at the beginning of the string, and one at the end, each moving towards the middle, with the condition being they have to show the same character as the other, and the loop ending when they both point to the middle, or the have switched relative positions.

Related

Similar solutions but different answers

I am facing difficulty while solving a problem where we have to check whether a string is a subsequence of another string or not.
A man with name M is allowed to marry a woman with name W, only if M is a subsequence of W or W is a subsequence of M.
A is said to be a subsequence of B if A can be obtained by deleting some elements of B without changing the order of the remaining elements.
Example -
john and johanna will give "YES" as output
kayla and jayla will give "NO" as output
johanna and john will give "YES" as output
My code is :
#include <iostream>
#include<string>
using namespace std;
bool checksub(string a, string b)
{
int pos=0;
for(int i=0; i<a.size(); i++)
{
int flag=0;
for(int j=pos; j<b.size(); j++)
{
if(b[j]==a[i])
{
flag=1;
pos=j;
break;
}
}
if(flag==0)
{
return false;
}
}
return true;
}
int main() {
// your code goes here
int t;
cin>>t;
while(t--)
{
string a,b;
cin>>a>>b;
if(a.size()==b.size())
{
if(a==b)
{
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;}
}
else if(a.size()>b.size()){
if(checksub(b,a))
{
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
}else{
if(checksub(a,b))
{
cout<<"YES"<<endl;
}else{
cout<<"NO"<<endl;
}
}
}
return 0;
}
The editorial of the question uses a similar approach. Can anybody tell me what's wrong with my code?
The editorial solution is given below :
#include <cstdio>
char M[25005], W[25005];
bool contains(const char *A, const char *B){
while(*A){
if(*B==*A)
B++;
A++;
}
return !*B;
}
int main(){
int T;
scanf("%d", &T);
while(T--){
scanf("%s %s", M, W);
puts(contains(M, W) || contains(W, M) ? "YES" : "NO");
}
return 0;
}
Link to the problem: https://www.codechef.com/problems/NAME2
Your code produces the wrong result with input AA BAB because it fails to account for the fact that you need to have two A in the second string.
You might be able to fix it by changing pos=j; to pos=j+1; but I'm not certain.
There really is no similarity between your code and the editoral code however. Even with my suggested fix (if it does work) your code is clearly less efficient than the editorial code because it scans the input strings repeatedly.
Got the correct answer just by changing pos=j+1 instead of pos=j. Then code will become similar to the pseudocode in the editorial. Thanks, everybody for answering.

SIGABRT error in cpp

I'm getting a SIGABRT error when I compile the following code(PALIN problem on SPOJ).The objective of the code is to find smallest palindromic number which should be greater than the given number, where given number can have upto 1000000 digits.
Link to the problem is: http://www.spoj.com/problems/PALIN/ It runs well on codeblocks but SPOJ returns SIGABRT error. Can someone explain the reason?
#include<iostream>
#include<string>
using namespace std;
string palinodd(string num)//to find next nearest palindrome for an odd digit number
{
string palin=num;
int flag=0;
for(int i=num.size()/2-1;i>-1;i--)
{
if(flag==0)//checks if the middle most digit should be incremented
{
if(num[i]<palin[num.size()-i-1])
flag=1;
else if(num[i]>palin[num.size()-i-1])
flag=-1;
}
palin[num.size()-1-i]=num[i];
}
if(flag!=-1)
palin[num.size()/2]++;
if(palin[num.size()/2]==':')//if the middle digit goes greater than 9
{
palin[num.size()/2]='0';
palin[num.size()/2-1]++;
palin[num.size()/2+1]++;
}
return palin;
}
string palineve(string num)//to find next nearest palindrome for an even digit number
{
string palin=num;
int flag=0;
for(int i=num.size()/2-1;i>-1;i--)
{
if(flag==0)//checks if middle digit should be incremented
{
if(num[i]<palin[num.size()-i-1])
flag=1;
else if(num[i]>palin[num.size()-i-1])
flag=-1;
}
palin[num.size()-1-i]=num[i];
}
if(flag!=-1)
palin[num.size()/2-1]++;
if(palin[num.size()/2-1]==':')//if the middle digit goes greater than 9
{
palin[num.size()/2-2]++;
palin[num.size()/2+1]++;
palin[num.size()/2-1]='0';
}
palin[num.size()/2]=palin[num.size()/2-1];//updates the middle number
return palin;
}
int main()
{
int t;
cin>>t;
while(t--)
{
string num="912496394";
string ans;
if(num.size()%2!=0)
ans=palinodd(num);
else
ans=palineve(num);
cout<<ans<<endl;
}
return 0;
}
Appreciate your effort, try to match c++ compiler, version in SPOJ and codeblocks. I tried your code with clang++-5.0 after changing num (912496394) to string but i didn't get expected results. I think you might have posted older version of your code, if possible you can post the updated code.
The process will be aborted with SIGABRT if there are any overflows in your code, as you are using more string operations you can refer below link which has some info on SIGABRT,
SIGABRT called when calling find() on a string element in an array
One suggestion on your approach to the problem, you can try to increment the input by one in a while loop until you find a palindrome or you reach largest number and print the results
The solution I found out for above problem is:
#include<iostream>
#include<string>
using namespace std;
string palinodd(string num)
{
string palin=num;
int flag=0;
for(int i=num.size()/2-1;i>-1;i--)
{
if(flag==0)
{
if(num[i]<palin[num.size()-i-1])
flag=1;
else if(num[i]>palin[num.size()-i-1])
flag=-1;
}
palin[num.size()-1-i]=num[i];
}
if(flag!=-1)
palin[num.size()/2]++;
if(palin[num.size()/2]==':')
{
palin[num.size()/2]='0';
palin[num.size()/2-1]++;
palin[num.size()/2+1]++;
}
for(int i=num.size()/2-1;i>0;i--)
{
if(palin[i]==':')
{
palin[i]='0';
palin[i-1]++;
}
}
for(int i=num.size()/2+1;i<num.size()-1;i++)
{
if(palin[i]==':')
{
palin[i]='0';
palin[i+1]++;
}
}
return palin;
}
string palineve(string num)
{
string palin=num;
int flag=0;
for(int i=num.size()/2-1;i>-1;i--)
{
if(flag==0)
{
if(num[i]<palin[num.size()-i-1])
flag=1;
else if(num[i]>palin[num.size()-i-1])
flag=-1;
}
palin[num.size()-1-i]=num[i];
}
if(flag!=-1)
palin[num.size()/2-1]++;
if(palin[num.size()/2-1]==':')
{
palin[num.size()/2-2]++;
palin[num.size()/2+1]++;
palin[num.size()/2-1]='0';
}
palin[num.size()/2]=palin[num.size()/2-1];
/*if any incremented digit becomes greater than 9,it shows a ':' so we make it 0 and increase previous(if ':' comes in the first half of the string)/next(if ':' comes in the last half of the sting) digit by 1.*/
for(int i=num.size()/2-2;i>0;i--)
{
if(palin[i]==':')
{
palin[i]='0';
palin[i-1]++;
}
}
for(int i=num.size()/2+1;i<num.size()-1;i++)
{
if(palin[i]==':')
{
palin[i]='0';
palin[i+1]++;
}
}
return palin;
}
int main()
{
int t;
cin>>t;
while(t--)
{
string num,ans;
cin>>num;
int cnt=0;
/*if all the digits in the string are 9, then the next palindromic number will have one more digit than the original number of digits. Thus, increasing the string length*/
for(int i=0;i<num.size();i++)
{
if(num[i]=='9')
cnt++;
}
if(cnt==num.size())
{
num[0]='1';
for(int i=1;i<num.size();i++)
num[i]='0';
num+='0';
}
if(num.size()%2!=0)
ans=palinodd(num);
else
ans=palineve(num);
cout<<ans<<endl;
}
return 0;
}

Why am I getting a WA in Faded Palindromes in Codechef even though I found no error till now in my code and its working fine for me?

I have been debugging and seeing this code for nearly a week now still I couldn't find any solution and thus hoping to get one from the fellow developers in stack overflow.
This is the solution of the Faded Palindrome problem of September Challenge Codechef This is the problem page
#include<iostream>
#include<vector>
#include<iterator>
#include<stdlib.h>
#include<cstdio>
#include<string>
using namespace std;
string def="-1";
int main()
{
int t;
cin>>t;
//vector<string> out(t);
string out[100];
for(int i=0;i<t;i++)
{
string inp;
cin>>inp;
if(inp.size()%2) //Checking wether the number of letters is odd
{
int counter=inp.size()/2;
int counter_back=counter-1;
int counter_front=counter+1;
if(inp[counter]=='.')
inp[counter]='a';
int not_fa=0;
while(counter_back>=0&&counter_front<inp.size())
{
if(inp[counter_back]==inp[counter_front])
{counter_back--;counter_front++;}
else if(inp[counter_back]=='.'&&inp[counter_front=='.']){
inp[counter_back]=inp[counter_front]='a';
counter_back--;counter_front++;
}
else if(inp[counter_back]=='.'){
inp[counter_back]=inp[counter_front];
counter_back--;counter_front++;
}
else if(inp[counter_front]=='.'){
inp[counter_front]=inp[counter_back];
counter_back--;counter_front++;
}
else{
not_fa=1;
break;
}
}
if(not_fa)
out[i]=def;
else
out[i]=inp;
}
else{ //Checking the number of letter is even
//cout<<inp.size();
int counter_front=(inp.size())/2;
//cout<<counter_front;
int counter_back=counter_front-1;
//cout<<counter_back;
int not_fa=0;
while(counter_back>=0&&counter_front<inp.size())
{
if(inp[counter_back]==inp[counter_front])
{//cout<<"*-";
counter_back--;counter_front++;}
else if(inp[counter_back]=='.'&&inp[counter_front]=='.'){
inp[counter_back]=inp[counter_front]='a';
counter_back--;counter_front++;
}
else if(inp[counter_back]=='.'){
//cout<<"--";
inp[counter_back]=inp[counter_front];
counter_back--;counter_front++;
}
else if(inp[counter_front]=='.'){
inp[counter_front]=inp[counter_back];
counter_back--;counter_front++;
}
else{
not_fa=1;
break;
}
}
if(not_fa)
out[i]=def;
else
out[i]=inp;
}
}
/*vector<string>::iterator itr;
for(itr=out.begin();itr!=out.end();itr++)
cout<<*itr<<endl;*/
for(int j=0;j<t;j++)
if(j==t-1)
cout<<out[j];
else
cout<<out[j]<<"\n";
return 0;
}
While your code may pass all the test cases presented in the problem statement, there are still more edge cases that your code doesn't cover. Here's a sample test case:
6
..
...
..e
a..a.v.
p..p
t.xzt
This should print:
aa
aaa
eae
avaaava
paap
tzxzt
instead it prints:
..
.a.
aaa
aa.a.aa
p..p
taxat
Hints:
The first if statement is not correctly handling the case where inp[b] and inp[f] are both '.'.
There is no need for doing two different things when |s| is even or odd.
Also, in the first else if statement, you probably meant inp[counter_front]=='.' instead of inp[counter_front=='.'].
if(inp[counter_back]==inp[counter_front]) is true if they both are equal to '.' so you won't fill that gap.

Unwanted output repetition and matrix search issues

This code is an attempt to search for a target value (item) in a 5x5 matrix that I hard-coded values into. It queries the user for the value to be searched for. The problem is, when I run the code it tells me "Item found!" regardless of the user input. Also, It appears to be repeating user input. For example, when I used "87" as the user input, this is my output:
What is the value you'd like to search for? 878787Item found!
I'm fairly new to C++ so forgive me if I did something stupid. The code is as follows:
#include <iostream>
#include <algorithm>
#include <array>
using namespace std;
int main()
{
int target;
int flag;
int mat[5][5]= //hardcoded the matrix data
{
{1,2,3,4,5},
{6,7,8,9,10},
{11,12,13,14,15},
{16,17,18,19,20},
{21,22,23,24,25}
};
cout<<"What is the value you'd like to search for? ";
cin>>target;
for(int x=0;x<5;x++)
{
for(int y=0;y<5;y++)
{
if (mat[x][y]==target)
{
flag=1;
break;
}
else
{
//do nothing
}
}
}
if(flag == 1)
{
cout<<"Item found!";
}
else
{
cout<<"Item not found.";
}
return 0;
}
As aslg mentioned in his comment you break only your inner loop, you need to beak the outer for(int x=0;x<5;x++) loop as well. You can do this after the inner loop by stating:
if(flag==0){
break;
}
But this is not a particularly elegant solution. I suggest you let the standard library do the job.
int* end = mat[0]+25;
int* found = std::find(mat[0],end,target);
if(found!=end)
{
cout<<"Item found!";
}
else
{
cout<<"Item not found.";
}
Whats going on here: In fact the static multidimensional 5x5 array is stored as a one-dimensional array of size 25. mat[0] points to its start and mat[0] + 25 to its end. std::find(start,end,target) returns the pointer to the target if it can be found within [start,end[, else end is returned.

My knight's tour algorithm possibly is running on an infinite loop

Here's the code i wrote.
#include "genlib.h"
#include <iostream>
#include <math.h>
#include "vector.h"
struct square
{
int x;
int y;
};
bool knighttour(square start,int &counter,int cb[][8]);
Vector <square> generatemoves (square start);
void Marksquare(int &cb,int ctr);
void Unmarksquare(int &cb);
bool IsLegal(square a,int cb[][8]);
int main()
{
int chessboard[8][8];
for (int i=0;i<8;i++)
for (int j=0;j<8;j++)
chessboard[i][j]=-1;
int counter=1;
for (int i=0;i<8;i++){
for (int j=0;j<8;j++){
square temp;
temp.x=i;
temp.y=j;
if (knighttour(temp,counter,chessboard))
{
for (int k=0;k<8;k++){
cout<<chessboard[k][0]<<chessboard[k][1]<<chessboard[k][2]<<chessboard[k][3]<<chessboard[k][4]<<chessboard[k][5];
cout<<chessboard[k][6]<<chessboard[k][7]<<endl;}
}
}
}
return 0;
}
bool knighttour(square pt,int &counter,int cb[][8])
{
Marksquare(cb[pt.x][pt.y],counter);
if (counter==64)
return true;
counter++;
Vector <square> temp = generatemoves(pt);
for (int i=0;i<temp.size();i++)
{
if (IsLegal(temp[i],cb))
knighttour(temp[i],counter,cb);
}
Unmarksquare(cb[pt.x][pt.y]);
counter--;
return false;
}
Vector <square> generatemoves (square start)
{
Vector <square> temp;
Vector <square> temp2;
square mv1;
mv1.x=start.x+2;
mv1.y=start.y+1;
temp.add(mv1);
square mv2;
mv2.x=mv1.x;
mv2.y=start.y-1;
temp.add(mv2);
square mv3;
mv3.y=start.y+2;
mv3.x=start.x+1;
temp.add(mv3);
square mv4;
mv4.y=start.y+2;
mv4.x=start.x-1;
temp.add(mv4);
square mv5;
mv5.x=start.x-2;
mv5.y=start.y+1;
temp.add(mv5);
square mv6;
mv6.x=start.x-2;
mv6.y=start.y-1;
temp.add(mv6);
square mv7;
mv7.y=start.y-2;
mv7.x=start.x-1;
temp.add(mv7);
square mv8;
mv8.y=start.y-2;
mv8.x=start.x+1;
temp.add(mv8);
for (int i=0;i<temp.size();i++)
if (temp[i].x>=0 && temp[i].x<=7 && temp[i].y>=0 && temp[i].y<=7)
temp2.add(temp[i]);
return temp2;
}
void Marksquare(int &a,int ctr)
{
a=ctr;
}
void Unmarksquare(int &a)
{
a=-1;
}
bool IsLegal(square a,int cb[][8])
{
if (cb[a.x][a.y]==-1)
return true;
else
return false;
}
A little explanation. I am using an int [8][8] to represent the board of chess and initially i put in every square of the board the number -1.
As the Knight moves it marks the square that he visits with the counter (int counter) and from there (and for all the legal moves the knight can take) makes recursive calls to find a path (the goal is to visit each square exactly once).
Once the counter hits 64 the function bool knighttour(square start,int &counter,int cb[][8])
must return true and the main program then should display "the knight's tour" as it is marked on the [8][8] chessboard.
I believe that the above code i provided runs on an infinite loop. I let it run for 3 minutes.
Theory says:
...It is important to note that an exhaustive brute force approach (one which iterates through all possible move sequences) can never be applied to the Knight's Tour problem (except for very small board sizes). For a regular 8x8 chess board, there are approximately 4×1051 possible move sequences,[9] and it would take an unfathomable amount of time to iterate through such a large number of moves.
So to ensure that your program works, try with smaller board size (say 4x4).
To ensure your program works for 8x8 in reasonable time you'll have to change the algorithm. There are many in addition to those listed here.
--edit--
also to ensure that your program is doing something, it's always a good idea to add some traces while you're still developing it.
E.g.
bool knighttour(square pt,int &counter,int cb[][8]) {
printf("\r%d ", counter); // <<<---
Marksquare(cb[pt.x][pt.y],counter);
if (counter==64)
return true;
counter++;
Vector <square> temp = generatemoves(pt);
for (int i=0;i<temp.size();i++)
{
if (IsLegal(temp[i],cb))
knighttour(temp[i],counter,cb);
}
Unmarksquare(cb[pt.x][pt.y]);
counter--;
return false;
}
This code probably tries to find all possible routes in knights tour and will return last found route.
Instead of
for (int i=0;i<temp.size();i++)
{
if (IsLegal(temp[i],cb))
knighttour(temp[i],counter,cb);
}
Try
for (int i=0;i<temp.size();i++)
{
if (IsLegal(temp[i],cb))
{
if(knighttour(temp[i],counter,cb))
{
return true;
}
}
}
One thing I see is that although you return true when counter==64 in knighttour, that doesn't get propagated, the function calling it will return false.. so you'll never notice it in main().
That said, even if you fix your algorithm it might not finish in your lifetime.