Find the next palindrome - c++

Given a number, I am trying to find the smallest palindrome number greater than given number. Here is my code:
#include<bits/stdc++.h>
using namespace std;
char a[1000005];
int main(){
int t,len,ni,nj,nk,i,j,k;
cin>>t;
while(t--){
cin>>a;
char ch=getchar();
len=strlen(a);
k=len-1;
for(i=0;i<len;i++){
if(a[i]!='9'){
break;
}
}
if(i==len){ //if all digits are 9
for(i=len-1;i>0;i--){
a[i]='0';
}
a[0]='1';
a[len]='1';
a[len+1]='\0';
}
else{
for(i=0;i<len/2;i++){
if(a[i]!=a[len-1-i]){ //check if number is already palindrome
break;
}
}
if(i==len/2){ //add 1 if it is already palindrome
j=len-1;
while(1){
nj=((int)a[j])-48;
nj++;
if(nj<10){
a[j]=nj+48;
break;
}
else{
a[j]=48;
j--;
}
}
}
for(i=0;i<len/2;i++){
if(a[i]==a[k]){ //compare first with last,second with second last...
k--;
}
else{
nk=((int)a[k])-48;
ni=((int)a[i])-48;
if(nk<ni){
a[k]=ni+48;
}
else{
j=k; a[j]=ni+48; j--;
while(1){
nj=((int)a[j])-48;
nj++;
if(nj<10){
a[j]=nj+48;
break;
}
else{
a[j]=48;
j--;
}
}
if(j<=i){
i=j-1;
k=len-j;
}
}
k--;
}
}
if(len%2==0){
a[len/2]=a[len/2-1];
}
}
cout<<a<<endl;
}
return 0;
}
My code is working fine for all the inputs I have tried, but it is not getting accepted. Is my code right?

Some of the reasons why this code might have been rejected are:
length of code: finding the smallest palindromic number greater than a given input can be done with a lot less code.
memory efficiency: ~1MB of memory is by far too much for operations that can easily be done in-place. The total memory required would simply be the size of the number plus a few additional integer-vars.
runtime efficiency: This problem could be solved in O(n), where n is the number of digits of the number. I don't quite get the way your code works - and to be honest I won't put any effort in understanding that mess -, but that doesn't exactly look linear (or even close to it).
#include <bits/stdc++.h>: This header is GNU-specific, compiler-specific, ... . This code might not even compile if the tester uses another compiler. Apart from that the compilation takes more time with this header and will produce a larger executable than if you'd simply include the required headers. The reasons why it's a bad idea to use this header are described here in a more extensive way.
I can only speculate about the reason(s) why the solution really was rejected. The least information required to answer this would be a link to the judge that rejected it - which should aswell give a reason why it was rejected.

Related

How to memoize or make recursive function with no apparent pattern?

Consider the following code, it was done for the Codeforces Round #731 (Div. 3), problem B https://codeforces.com/contest/1547/problem/B
In short, you are given a string and you are supposed to check if it's possible to create that string by sequentially adding letters in alphabetical order in either the front to the back of a string that starts empty.
Ex. the string "bac", you would first make the empty string be "a", then it can be either "ba" or "ab", then we try again and we get that based on the last result it now can be "bac", "cba", "abc", "cab". We get that is possible so we return true.
We can only do this procedure up to 26 times.
My code would make a tree, grabbing a base string as the head, and two children nodes, one with the letter added to the front and one with the letter added to the back, if neither worked out, then I would repeat it again with the children nodes.
I rewrote my solution and sent a completely different one, but I still wanted to know if there was a way to optimize so it could actually be executed. The code works if n is around 14 or 15, it stutters a little bit but can finish; but once it goes to 20 it will not even finish.
#include <iostream>
#include <string>
using namespace std;
bool solve(string fs,string s = "", int n = 0){
if(s == fs){
return true;
}
if(n > 26 || s.size() > fs.size()){
return false;
}
if(solve(fs,s+(char)(96+n+1),n+1) ||solve(fs,(char)(96+n+1)+s,n+1)){
return true;
}
return false;
}
int main(){
int t;cin>>t;
for(int i = 0; i < t; i++){
string p;
cin>>p;
if(solve(p)){
cout<<"YES"<<endl;
}
else{
cout<<"NO"<<endl;
}
}
}```
You are doing brute force approach which is time complexity of n * 2^n. And it looks pretty reasonable to fail(TLE) when n is around 20 (taking into account that t is up to 10000)
I cannot come up with a way for efficient memoization, however this problem can easily be solved with greedy approach. You don't have to check all the combinations. Check out the official editorial

Why is my for loop running only 2 times instead of 10?

I am trying to find the third highest number in the array with O(n) space and time complexity.
MY program is obviously wrong but that is not the problem.
My for loop in the thirdhighestnum function seem to running only 2 times. I can't seem to find the reason for it. Can anyone help me. Sorry for such basic question I am a beginner here.
#include<iostream>
using namespace std;
int thirdhighestnum(int a[],int size)
{
cout<<" "<<size<<endl;
int first=a[0],second=0,third=0;
for(int i=1;i<size;i++)
{
cout<<a[i]<<";"<<endl;
if(a[i]>first)
{
first=a[i];
if(a[i+1]>first)
{
second=first;
first=a[i+1];
if(a[i+2]>first)
{ third=second;
second=first;
first=a[i+2];
}
}
cout<<i<<endl
return third;
}
}
}
int main()
{ int num,a[10];
cout<<"Enter the elements in the array"<<endl;
for(int i=0;i<10;i++)
cin>>a[i];
cout<<"Third highest number is "<<thirdhighestnum(a,10)<<endl;
return 0;
}
It's the location of your return third statement. The moment any number is larger than the first number, it exits the thirdhighestnum function and returns a value. Put it outside your for loop and it should be fine.
Actually it is executing only one time i.e. the first iteration only. When i=1 then it prints a[1] i.e. 2; after that it prints i i.e. 1 so it appears as 2;1 here you think it is printing 2 numbers.
The main problem is your return third statement which terminates your for loop in first iteration only.
This is known as nth_element and library function can do this for you.
As for why your code fails, there is a flaw in your logic
for(int i=1;i<size;i++)
{
// some code
if(a[i]>first)
{
// some more code
cout<<i<<endl
return third;
}
}
So your code exits the first time a[i] is greater than first.
[edit - After reading comments]
The generic name for this type of algorithm is a QuickSelect. It is unlikely you will find a faster algorithm, as this has been the subject of years of academic study.

cout doesn't works properly on my program, can somebody help me?

enter image description hereI am using the STL in c++ and inside a bucle the cout doesn't prints correctly a float.
my program ads values to a vector and then passes it to a function to see if the condition exist, actually it works perfectly but just the cout doesn't word, I already tried using printf() but it gave the same result.
note:please algo give me feedback on my question is the first time i do one and English is not my natal language
my code:
#include<bits/stdc++.h>
#include<vector>
using namespace std;
void isthereanumber(vector<float> array);
int main(){
string ans;vector<float> array;float number;
do{
fflush(stdin);
cout<<"insert a value for the vector: "<<endl;
cin>>number;
array.push_back(number);
fflush(stdin);
cout<<"would you like to keep adding values to the vector? "<<endl;
getline(cin,ans);
}while(ans.compare("yes")==0);
isthereanumber(array);
return 0;
}
void isthereanumber(vector<float> array){
float suma =0;
for(vector<float>::iterator i=array.begin();i!=array.end();i++){
for(vector<float>::iterator j=array.begin();j!=array.end();j++){
if(i!=j){
suma = suma+array[*j];
}
}
if(suma=array[*i]){
cout<<"there is a number that the addition of every number in the array except the number is equal to the number \n";fflush(stdin);
cout<<"the number is: "<<suma;/*here is the cout that doesnt works properly or perhabs is something else i don't know*/
return;
}
}
cout<<"there is not a number with such a condition: ";
return;
}
As stated by cleggus already there are some issues present. Those need to be adressed first. After that there's a logical error in that suma just keeps growing.
Given the input 5,5,10 once we test for 10 we would like suma to be set to 0 again for it to work but it will be something like 30 now instead.
That can be solved by moving suma inside the outer loop.
Working example for input 5,5,10: https://godbolt.org/z/gHT6jg
I think you may have a couple of issues...
In your for loops you are creating iterators to the vector, but rather than just dereferencing them to access the indexed element you are dereferencing them and then using that as an index to the same vector.
Also Your last if statement has an assignment = rather than a comparison ==.
I believe this is closer to what you are trying to achieve (sorry I haven't had time to compile and check):
for(vector<float>::iterator i=array.begin();i!=array.end();i++){
for(vector<float>::iterator j=array.begin();j!=array.end();j++){
if(i!=j){
suma = suma+*j;
}
}
if(suma==*i){
cout<<"there is a number that the addition of every number in the array except the number is equal to the number \n";fflush(stdin);
cout<<"the number is: "<<suma;/*here is the cout that doesnt works properly or perhabs is something else i don't know*/
return;
}
}

Quick sort algorithm code

I'm trying to implement a quick sort that sorts numbers and words based on the number value. I can't seem to figure out how to fix the following code to work right.
if (high!=low&& high>low)//compares hashes and finds the number in the middle. swaps hashes and corresponding words
{
long one=hash[low];
long two=hash[high];
long three = hash[high/2];
if((one<=two&&one>=three)||(one<=three&&one>=two))
{
swap(hash[low], hash[high]);
swap(copyOfWords[low], copyOfWords[high]);
}
else if((three<=one&&three>=two)||(three<=two&&three>=one))
{
swap(hash[high/2], hash[high]);
swap(copyOfWords[high/2], copyOfWords[high]);
}
else
{
}
int i=low;
int j=high-1;
while(i!=j&&i<j)
{
while(hash[i]<hash[high]&&i<j)// find higher numbers and lower numbers then the middlle and swaps them
{
i++;
}
while(hash[j]>hash[high]&&i<j)
{
j--;
}
if(i==j||i>j)
{
}
else
{
swap(hash[i],hash[j]);
swap(copyOfWords[i],copyOfWords[j]);
i++;
j--;
}
}
swap(hash[i],hash[high]);
swap(copyOfWords[i], copyOfWords[high]);
quickSort(low, j-1);//recursive
quickSort(j+1, high);
}
}
I know the values in hash and copyOfWords are correct because when I use shell sort, it sorts them the right way. for example if there are two words, copyOfWOrds[0]="1994," and copyOfWords[1]="a" then hash[0]=549456039 and hash[1]=197000000, but the sort puts them a 1994, a instead of a 1994,. It causes more problems with more elements. Any help would be appreciated. Thanks
Why don't you go to the quick sort wiki page and see how it's done?
Your code tries to do unnecessary stuffs and eventually trips over its own feet. Keep it simple and it will work.
And Btw Quicksort works very well on arrays, so it's a shame to make one version where the array is hard-coded.

ARRAYS DEBUGGING incorrect outputs, complex algorithm

I made this algorithm, i was debugging it to see why it wasnt working, but then i started getting weird stuff while printing arrays at the end of each cycle to see where the problem first occurred.
At a first glance, it seemed my while cycles didn't take into consideration the last array value, but i dunno...
all info about algorithm and everything is in the source.
What i'd like to understand is, primarily, the answer to this question:
Why does the output change sometimes?? If i run the program, 60-70% of the time i get answer 14 (which should be wrong), but some other times i get weird stuff as the result...why??
how can i debug the code if i keep getting different results....plus, if i compile for release and not debug (running codeblocks under latest gcc available in debian sid here), i get most of the times 9 as result.
CODE:
#include <iostream>
#include <vector>
/*void print_array
{
std::cout<<" ( ";
for (int i = 0; i < n; i++) { std::cout<<array[i]<<" "; }
std::cout<<")"<<std::endl;
}*/
///this algorithm must take an array of elements and return the maximum achievable sum
///within any of the sub-arrays (or sub-segments) of the array (the sum must be composed of adjacent numbers within the array)
///it will squeeze the array ...(...positive numbers...)(...negative numbers...)(...positive numbers...)...
///into ...(positive number)(negative number)(positive number)...
///then it will 'remove' any negative numbers in case it would be convienent so that the sum between 2 positive numbers
///separated by 1 negative number would result in the highest achievable number, like this:
// -- (3,-4,4) if u do 'remove' the negative number in order to unite the positive ones, i will get 3-4+4=3. So it would
// be better not to remove the negative number, and let 4 be the highest number achievable, without any sums
// -- (3,-1,4) in this case removing -1 will result in 3-1+4=6, 6 is bigger than both 3 and 4, so it would be convienent to remove the
// negative number and sum all of the three up into one number
///so what this step does is shrink the array furthermore if it is possible to 'remove' any negatives in a smart way
///i also make it reiterate for as long as there is no more shrinking available, because if you think about it not always
///can the pc know if, after a shrinking has occured, there are more shrinkings to be done
///then, lastly, it will calculate which of the positive numbers left is highest, and it will choose that as remaining maximum sum :)
///expected result for the array of input, s[], would be (i think), 7
int main() {
const int n=4;
int s[n+1]={3,-2,4,-4,6};
int k[n+1]={0};
///PRINT ARRAY, FOR DEBUG
std::cout<<" ( ";
for (int i = 0; i <= n; i++) { std::cout<<k[i]<<" "; }
std::cout<<")"<<std::endl;
int i=0, j=0;
// step 1: compress negative and postive subsegments of array s[] into single numbers within array k[]
/*while (i<=n)
{
while (s[i]>=0)
{
k[j]+=s[i]; ++i;
}
++j;
while (s[i]<0)
{
k[j]+=s[i]; ++i;
}
++j;
}*/
while (i<=n)
{
while (s[i]>=0)
{
if (i>n) break;
k[j]+=s[i]; ++i;
}
++j;
while (s[i]<0)
{
if (i>n) break;
k[j]+=s[i]; ++i;
}
++j;
}
std::cout<<"STEP 1 : ";
///PRINT ARRAY, FOR DEBUG
std::cout<<" ( ";
for (int i = 0; i <= n; i++) { std::cout<<k[i]<<" "; }
std::cout<<")"<<std::endl;
j=0;
// step 2: remove negative numbers when handy
std::cout<<"checked WRONG! "<<unsigned(k[3])<<std::endl;
int p=1;
while (p!=0)
{
p=0;
while (j<=n)
{
std::cout<<"checked right! "<<unsigned(k[j+1])<<std::endl;
if (k[j]<=0) { ++j; continue;}
if ( k[j]>unsigned(k[j+1]) && k[j+2]>unsigned(k[j+1]) )
{
std::cout<<"checked right!"<<std::endl;
k[j+2]=k[j]+k[j+1]+k[j+2];
k[j]=0; k[j+1]=0;
++p;
}
j+=2;
}
}
std::cout<<"STEP 2 : ";
///PRINT ARRAY, FOR DEBUG
std::cout<<" ( ";
for (int i = 0; i <= n; i++) { std::cout<<k[i]<<" "; }
std::cout<<")"<<std::endl;
j=0; i=0; //i will now use "i" and "p" variables for completely different purposes, as not to waste memory
// i will be final value that algorithm needed to find
// p will be a value to put within i if it is the biggest number found yet, it will keep changing as i go through the array....
// step 3: check which positive number is bigger: IT IS THE MAX ACHIEVABLE SUM!!
while (j<=n)
{
if(k[j]<=0) { ++j; continue; }
p=k[j]; if (p>i) { std::swap(p,i); }
j+=2;
}
std::cout<<std::endl<<"MAX ACHIEVABLE SUM WITHIN SUBSEGMENTS OF ARRAY : "<<i<<std::endl;
return 0;
}
might there be problems because im not using vectors??
Thanks for your help!
EDIT: i found both my algorithm bugs!
one is the one mentioned by user m24p, found in step 1 of the algorithm, which i fixed with a kinda-ugly get-around which ill get to cleaning up later...
the other is found in step2. it seems that in the while expression check, where i check something against unsigned values of the array, what is really checked is that something agains unsigned values of some weird numbers.
i tested it, with simple cout output:
IF i do unsigned(k[anyindexofk]) and the value contained in that spot is a positive number, i get the positive number of course which is unsigned
IF that number is negative though, the value won't be simply unsigned, but look very different, like i stepped over the array or something...i get this number "4294967292" when im instead expecting -2 to return as 2 or -4 to be 4.
(that number is for -4, -2 gives 4294967294)
I edited the sources with my new stuff, thanks for the help!
EDIT 2: nvm i resolved with std::abs() using cmath libs of c++
would there have been any other ways without using abs?
In your code, you have:
while (s[i]>=0)
{
k[j]+=s[i]; ++i;
}
Where s is initialized like so
int s[n+1]={3,-2,4,-4,6};
This is one obvious bug. Your while loop will overstep the array and hit garbage data that may or may not be zeroed out. Nothing stops i from being bigger than n+1. Clean up your code so that you don't overstep arrays, and then try debugging it. Also, your question is needs to be much more specific for me to feel comfortable answering your question, but fixing bugs like the one I pointed out should make it easier to stop running into inconsistent, undefined behavior and start focusing on your algorithm. I would love to answer the question but I just can't parse what you're specifically asking or what's going wrong.