Unwanted output repetition and matrix search issues - c++

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.

Related

Why does my control function do the opposite of what it's supposed to do?

int control(int n, data a[], string cod){
for(int i = 0 ; i<n ; i++){
if(cod == a[i].code)
return i;
}
return -1;
}
Hello, everyone! this is my control function. it's used to check if a code that has been input by a user already exists in the struct. This is what happens in the "input" function:
void input(int &n, data a[]){
string code;
do{
cout<<"\nInput the code: ";
cin>> code;
if((control(n,a,code))>0)
a[n].code=code;
else
cout<<"\nThe code you've input already exists. Please try again.";
}while((control(n,a,code)) == -1);
n++;
}
There are two problems:
everytime i input a code it tells me that it already exists, even though it's my first time.
it doesn't make me try again, even though the code already exists.
Let's start by indenting your code so we can more easily understand what it does:
int control(int n, data a[], string cod) {
for (int i = 0; i < n; i++)
{
if (cod == a[i].code)
return i;
}
return -1;
}
Ah, so it scans through an array, and returns a value greater than or equal to 0 if a string is present, or -1 if it's absent. Then let's consider the code that uses it:
void input(int &n, data a[])
{
string code;
do
{
cout << "\nInput the code: ";
cin >> code;
if ((control(n, a, code)) > 0)
a[n].code = code;
else
cout << "\nThe code you've input already exists. Please try again.";
} while ((control(n, a, code)) == -1);
n++;
}
So this accepts the code if the return value was greater than 0, and otherwise rejects the code as already existing. This is mostly backwards, but not exactly even that.
My suggestion would be to start by defining an enumeration to give meaningful names to the values you're returning. This makes it much easier to keep track of what's going on:
enum { DUPLICATE, UNIQUE };
int control(int n, data a[], string cod) {
for (int i = 0; i < n; i++)
{
if (cod == a[i].code)
return DUPLICATE;
}
return UNIQUE;
}
Now it's much easier to get our condition correct, and much more obvious if we react to it incorrectly:
if (control(n, a, code) == UNIQUE)
a[n].code = code;
else
cout << "\nThe code is a duplicate";
Or, if you prefer to reverse the condition, it's still easy to get correct:
if (control(n, a, code) == DUPLICATE)
cout << "\nThe code is a duplicate";
else
a[n].code = code;
But in particular, if you accidentally get things backwards, it'll be pretty obvious:
if (contro(n, a, code) == UNIQUE)
cout << "\nThe code is a duplicate";
At least to me, the contrast between "UNIQUE" on one line, and "duplicate" immediately below it seems fairly obvious.
Other Points to Consider
I'd advise against having:
using namespace std;
...in your code, as you apparently do right now. This is a bad habit that saves a little typing now, but can lead to considerable grief in the long term.
I'd also look up std::set and std::unordered_set, which can already do (more efficiently) what you're using your data array to do.
If/when you do need something array-like in C++, you probably want to use an std::array or std::vector rather than the built-in array type. They're much more convenient and help prevent quite a few errors.
I'd try to come up with a better name than control for a function that tries to show whether a code is already in use. control is such a generic name, it's almost impossible to guess what it's supposed to accomplish without looking at its content. A good name for a function does a great deal to clarify the code that uses it, and show what you intend that piece of code to accomplish:
std::cin >> new_code;
if (isDuplicate(new_code))
std::cerr << "The code you entered is a duplicate. Please try again\n";
else
codes.add(new_code);
do{
cout<<"\nInput the code: ";
cin>> code;
if((control(n,a,code))>0)
a[n].code=code;
else cout<<"\nThe code you've input already exists. Please try again.";
}while((control(n,a,code))==-1);
I see at least two problems here:
control returns 0 when the element is found at the first position, you check for >0 in the condition
if the loop body sucessfully inserts the element then while((control(n,a,code))==-1); results in an endless loop.
I suggest you to use std::find_if to check if an element is already present. With a std::vector thats:
#include <string>
#include <vector>
#include <algorithm>
struct data {
std::string code;
};
int main() {
std::vector<data> v;
std::string foo = "test";
auto it = std::find_if(v.begin(),v.end(),[foo](auto x){ return x.code == foo;});
bool found = (it == v.end());
}
Also consider to use a std::set if you want a container with unique entries.

How to create a array that lets user know they are out-of-bounds?

I'm trying to create a program that helps a user create an array index starting at any integer.
It should also notify the user during the execution/accessing the array component that is out-of-bounds.
This is what I have so far.
#include <iostream>
using namespace std;
int main(){
class safeArray;
};
const int CAPACITY=5;
I have set the capacity of the array to 5 so there can be a limit. Leaving the user to be able to go out of bounds.
class safeArray() {
userArray= new int [CAPACITY];
The user will be able to create a new int value for each slot in the array.
cout <<"Enter any integers for your safe userArray:";
if (int=0;i<CAPACITY;i++) {
cout<<"You are in-bounds!";
}
else (int=0;i>CAPACITY;i++){
cout<<"You are OUT-OF-BOUNDS!";
cout<<endl;
return 0;
};
I went with an if-else statement in order to check the array subscript?
I'm new to C++ so any clarification of errors or methods on how to simplify it would be helpful.
Thank you.
Your if statements should just read:
if (i<CAPACITY && i>0) {
cout<<"You are in-bounds!";
}
else if (i>CAPACITY){
cout<<"You are OUT-OF-BOUNDS!";
cout<<endl;
return 0;
};
Also, what happens in the edge case when i == capacity? Your code doesn't handle this case at all.
To make this neater, you could format it with only one if/else statement
if (i<CAPACITY && i>0) { // Or should this be (i<=CAPACITY)??? depends on whether 0 is an index or not
cout<<"You are in-bounds!";
} else {
cout<<"You are OUT-OF-BOUNDS!";
cout<<endl;
return 0;
};
Instead of handling memory management you could use a standard container such as std::vector for dynamic "arrays" or std::array for fixed size arrays.
std::array has zero overhead on all major compilers and is more or less a C++ wrapper around C arrays.
In order to let the user know when the index is out of bounds most standard containers provide the at(std::size_t n) method (e.g. std::vector::at) that do all the rage checking for you and throw a std::out_of_range exception when supplying an invalid index/position.
All you have to do now is catch that exception and print a message if you want to.
Here's a little example:
#include <iostream>
#include <array>
int main() {
std::array<int, 12> arr;
try {
std::cout << arr.at(15) << '\n';
} catch (std::out_of_range const &) {
std::cout << "Sorry mate, the index you supplied is out of range!" << '\n';
}
}
live preview - ideone.com

Find next largest palindrome number

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.

How can I fix a SPOJ time limit exceeded error on the STAMPS challenge?

Here is the link for the problem: http://www.spoj.com/problems/STAMPS/;
here is the ideone link for the current code: http://ideone.com/AcHfc6;
here is the code:
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
int main()
{
int t,x,n,sum,sum2,count,i,j;
scanf("%d",&t);
for(j=1;j<=t;j++)
{
cin>>x>>n;
sum=0;
int offer[n];
for(i=0;i<n;i++)
{
cin>>offer[i];
sum+=offer[i];
sort(offer,offer+n);
}
if(sum>=x)
{
sum2=0;
count=0;
for(i=n-1;i>=0;i--)
{
sum2+=offer[i];
if(sum2<=x)
count++;
else
break;
}
cout<<"Scenario #"<<j<<":"<<endl;
cout<<count<<endl;
cout<<endl;
}
else
{
cout<<"Scenario #"<<j<<":"<<endl;
cout<<"impossible"<<endl;
cout<<endl;
}
}
return 0;
}
The code gives the right answers for the given test cases but it causes TLE. I've tried converting my cin's and cout's to scanf/printf but, weirdly enough, the answers were not the same and I don't know how the answers were different from each other.
What's going wrong?
I suspect your main problem is here:
for(i=0;i<n;i++)
{
cin>>offer[i];
sum+=offer[i];
sort(offer,offer+n);
}
You sort the data for every number that's entered. Also, you sort random data because you only have i rows of valid data in the array, not n rows. The sort should be done once, outside the loop:
for(i=0;i<n;i++)
{
cin>>offer[i];
sum+=offer[i];
}
sort(offer,offer+n);

C++: How do you create a return function that returns a vector/array?

This is the motivation behind the code. There is a boy named Bob and its his birthday today. He invites 50 friends over but not all of his friends want to buy him gifts. Bob is presented with 50 presents, though some of them are empty. His good friends tell him to close every 2nd box. For every third box, he is supposed to change every closed to open and every open to closed. He continues to do this for every n-th box where n is less than 50. The open boxes in the end will have the presents.
This is supposed to assist me in figuring out a problem for my math class, but I am not aware of all the complicated aspects of C++ programming. I want my string getValue(vector &arr) to return an array/vector. This code doesn't compile but it shows what I'm trying to do.
#include <iostream>
#include <vector>
#include<algorithm>
using namespace std;
string getValue(vector<string> &arr);
int main()
{
vector<string> myArr(2);
vector<string> newArr(2);
for(int i=2; i <= 50; i++)
{
if(i%2==0)
{
myArr.push_back("close");
}
else
{
myArr.push_back("open");
}
}
newArr = getValue(myArr);
for(int i=2; i <=50; i++)
{
cout << i << " " << newArr[i] << endl;
}
}
string getValue(vector<string> &arr)
{
for(int i=2; i <=50; i++)
{
if(arr[i]=="close")
{
arr[i]="open";
}
else if(arr[i]=="open")
{
arr[i]="close";
}
}
return arr;
}
You can't make your string getValue(vector<string> &arr) return an array/vector. It can only return a string. If you want a function to return an array/vector, then you have to say so in the function signature.
You're passing the vector into getValue() by reference, which means changes you make to it in that function will affect the original (in other words, you're not operating on a copy of the vector - you're actually operating on the vector).
So you don't need to return anything from getValue() - just make it void and it should do what you want.
string getValue(vector &arr) - the return type is string, not vector. You need to change its return type or set it to none.
PS:
newArr = getValue(myArr);
it's behind the SCOPE and it's wrongly positioned...
damn, third PS, wrong code rules are assigned
For the syntax part :-
The return type of the function is a string. Change it to vector for
your function to work properly.
You can simply declare the vectors globally. This will eliminate the
need to pass it to the function as well as return it.
For the logic part :-
Your question says that Bob toggles every third box but in your program Bob is changing every box to open if it is closed and every box to close if it is open. If what you wrote in the question is correct your code should be like this.
#include <iostream>
#include <vector>
using namespace std;
void getValue();
vector<string> myArr(2);
int main()
{
for(int i=2; i <= 50; i++)
{
if(i%2==0)
{
myArr.push_back("close");
}
else
{
myArr.push_back("open");
}
}
getValue();
for(int i=2; i <=50; i++)
{
cout << i << " " << myArr[i] << endl;
}
}
void getValue()
{
for(int i=3; i <=50; i+=3)
{
if(myArr[i]=="close")
{
myArr[i]="open";
}
else if(myArr[i]=="open")
{
myArr[i]="close";
}
}
}