MAgic Square function C++ - c++

This is my last function for my magic square and for some reason it's giving me an error that there is "'[int]' for array subscript" but I don't know what that means, if someone could help explain what I have to do.
bool Square::is_magic()
{
for (i = 0; i < size-1; i++)
{
if (sum_row[i] != sum_row[i+1])
return false;
if (sum_col[i] != sum_col[i+1])
return false;
}
if (sum_row[0] != sum_col[0])
return false;
if (sum_row[0] != sum_maindiag[0])
return false;
if (sum_row[0] != sum_other[0])
return false;
return true;
}

Ok everybody was beginer at some time. I really recommend you to read one or two books focused on c++. (Personally I learned programming with "Learn c++ in 21 days", many complain but it was good start for me).
And for the code. Not sure that it's what you need, it should go like this:
bool Square::is_magic()
{
int i;
for (i = 0; i < size-1; i++)
{
if (sum_row[i] != sum_row[i+1])
return false;
if (sum_col[i] != sum_col[i+1])
return false;
}
if (sum_row[0] != sum_col[0])
return false;
if (sum_row[0] != sum_maindiag[0])
return false;
if (sum_row[0] != sum_other[0])
return false;
return true;
}
Some comments:
You don't need brackets for 1 command after if,for,while statement
Suggest using if -> else if -> else. Here it doesn't matter because you jump out of function as soon as you find something not correct, but in case you would continue in code you would check other statements even if it wasn't necessary.
Get used to some style, make your own or copy someone's. Personally I use brackets this way:
if (something != somethingElse){
doSomeNastyThings();
doEvenMore();
}
Good luck..
Edit: added variable declaration int for statement, updated brackets (clever idea as last 3 if-s aren't using index)

If statements are formatted like this:
if (condition) {
do_this()
}
not like this:
{
if (condition)
do_this()
}
They way you're formatting your code you're closing your for loop after two lines, which I imagine is not what you're trying to do (since you're referring to var i afterwards).

Related

What is the most efficient way to return results from recursion?

There are 2 possible ways that I am familiar with while returning a boolean/integer value from a recursive function that defines is the operation carried out was a success or not.
Using static variables inside the recursive function. Changing values in the recursive calls and then returning the final value once everything is done.
Passing the result variable by reference to the recursive function and then manipulating its values in the function and then checking if the value corresponds to the result or not.
void Graph::findPath(string from, string to)
{
int result = 0;
if (from == to) cout<<"There is a path!"<<endl;
else
{
findPathHelper(from, to, result);
if (result) cout<<"There is a path!"<<endl;
else cout<<"There is not a path!"<<endl;
}
}
void Graph::findPathHelper(string from, string toFind, int &found)
{
for (vector<string>::iterator i = adjList[from].begin(); i != adjList[from].end(); ++i)
{
if (!(toFind).compare(*i))
{
found = 1;
break;
}
else
findPathHelper(*i, toFind, found);
}
}
Is there a better way to achieve this?
Thank You
I have changed your implementation to use a return value
bool Graph::findPathHelper(const string& from, const string& toFind)
{
for (vector<string>::iterator i = adjList[from].begin(); i != adjList[from].end(); ++i)
{
// I have assumed you comparison was incorrect - i.e. toFind == *i is that you want
// toFind == *i - The two strings are equal - Thus found
// or
// Recurse on *i - Have we found it from recursion
if (toFind == *i || findPathHelper(*i, toFind)) {
return true;
}
}
// We have searched everywhere in the recursion and exhausted the list
// and still have not found it - so return false
return false;
}
You can return a value in the recursive function and use that returned value for checking if it was success or not in subsequent calls.
Using static variable for this purpose may work but it's generally not a good IDEA and many consider it as bad practice.
Look into the below link which explains why we must avoid static or global variables and what kind of problems it could lead to during recursion.
http://www.cs.umd.edu/class/fall2002/cmsc214/Tutorial/recursion2.html
Note: I do not have enough reputation still to make a comment; and therefore i have posted this as answer.

Is it possible to embed "for loop" inside an "if statement" to compare multiple condition before continuing using c++

In this program, the user must type in an 3 letter departing airport code (userFlight) and I will give them back the possible destinations. To check that what they typed in is one of the valid airport codes (departureAirport) I want to compare userFlight and make sure it is one of the possible departureAirports which I have stored in a vector called flights[]. This code obviously isn't working, but is there a similar way to accomplish this?
if
(for (j = 0, j < flights.size, j++)
{
(userFlight != flights[j].departAirport)
})
{return errorCode};
else
{//doSomething()};
If it has a operator< inside which does compare like your condition, how about
if(std::find(flights.begin(), flights.end(), userFlight) != flights.end())
{
/* found */
}
else
{
/* not found */
}
Else, if you don't like that, just check if the loop runs through all indices:
size_t i;
for (i = 0, i < flights.size, i++)
{
if(userFlight == flights[i].departAirport)
break;
}
if(i < flights.size)
{
/* found */
}
else
{
/* not found */
}
But no, a syntax like you want doesn't exist.
The code structure you were aiming for is:
for (j = 0; j < flights.size(); j++)
if (userFlight == flights[j].departAirport)
break;
if ( j == flights.size() ) // we got to the end
return errorCode;
doSomething(j);
However, this is a C-like code style. Not that there is anything wrong with that, but C++ allows for algorithms to be expressed more abstractly (and therefore, easier to read and maintain). IMHO it would be better to use one of the other suggestions such as std::set or std::find_if.
It sounds like you actually want to have a std::set of departing airports.
std::set<std::string> departing_airports = {"DTW", "MKE", "MSP", };
assert(departing_airports.count("DTW") == 1);
Yet another option is std::any_of. Assuming flights contains objects of type Flight:
if (std::any_of(std::begin(flights), std::end(flights),
[&](const Flight& f) { return userFlight == f.departAirport; }))
return errorCode;
doSomething();

iterating vector of strings C++

The code is to read instructions from text file and print out graphic patterns. One is my function is not working properly. The function is to read the vectors of strings I've got from the file into structs.
Below is my output, and my second, third, and sixth graphs are wrong. It seems like the 2nd and 3rd vectors are not putting the correct row and column numbers; and the last one skipped "e" in the alphabetical order.
I tried to debug many times and still can't find the problem.
typedef struct Pattern{
int rowNum;
int colNum;
char token;
bool isTriangular;
bool isOuter;
}Pattern;
void CommandProcessing(vector<string>& , Pattern& );
int main()
{
for (int i = 0; i < command.size(); i++)
{
Pattern characters;
CommandProcessing(command[i], characters);
}
system("pause");
return 0;
}
void CommandProcessing(vector<string>& c1, Pattern& a1)
{
reverse(c1.begin(), c1.end());
string str=" ";
for (int j = 0; j < c1.size(); j++)
{
bool foundAlpha = find(c1.begin(), c1.end(), "alphabetical") != c1.end();
bool foundAll = find(c1.begin(), c1.end(), "all") != c1.end();
a1.isTriangular = find(c1.begin(), c1.end(), "triangular") != c1.end() ? true : false;
a1.isOuter = find(c1.begin(), c1.end(), "outer") != c1.end() ? true : false;
if (foundAlpha ==false && foundAll == false){
a1.token = '*';
}
//if (c1[0] == "go"){
else if (c1[j] == "rows"){
str = c1[++j];
a1.rowNum = atoi(str.c_str());
j--;
}
else if (c1[j] == "columns"){
str = c1[++j];
a1.colNum = atoi(str.c_str());
j--;
}
else if (c1[j] == "alphabetical")
a1.token = 0;
else if (c1[j] == "all"){
str = c1[--j];
a1.token = *str.c_str();
j++;
}
}
}
Before debugging (or posting) your code, you should try to make it cleaner. It contains many strange / unnecessary parts, making your code harder to understand (and resulting in the buggy behaviour you just described).
For example, you have an if in the beginning:
if (foundAlpha ==false && foundAll == false){
If there is no alpha and all command, this will be always true, for the entire length of your loop, and the other commands are all placed in else if statements. They won't be executed.
Because of this, in your second and third example, no commands will be read, except the isTriangular and isOuter flags.
Instead of a mixed structure like this, consider the following changes:
add a default constructor to your Pattern struct, initializing its members. For example if you initialize token to *, you can remove that if, and even the two bool variables required for it.
Do the parsing in one way, consistently - the easiest would be moving your triangular and outer bool to the same if structure as the others. (or if you really want to keep this find lookup, move them before the for loop - you only have to set them once!)
Do not modify your loop variable ever, it's an error magnet! Okay, there are some rare exceptions for this rule, but this is not one of them.
Instead of str = c1[++j];, and decrementing later, you could just write str = c1[j+1]
Also, are you sure you need that reverse? That makes your relative +/-1 indexing unclear. For example, the c1[j+1 is j-1 in the original command string.
About the last one: that's probably a bug in your outer printing code, which you didn't post.

Postive or negative null check in if-statement

I do a lot of null checking in my code, and usually I will check for not null before going on to my for or more if/else statements.
For example:
if(x!=null) {
for(int y:x) {
if(y.property1 != null) {
if( y.property < n) {
}
} else {
}
}
}
Is the following better practice?
if(x ==null) {
//exit or w/e you want to do
}
for(int y:x) {
if(y ==null){
}
if(y<0) {
}
}
No, they are the same to the engine, doesn't make any difference to the engine. It depends on your logic, but here, it's the same, dude
It doesn't make any difference... Equal / Negate Equal execute same instruction cycle.
But its always a good practice to check for all required data before manipulating any calculation
These achieve the same end. It would be up to your personal preference.

Find the hidden Infinite Loop

I'm working on this problem and my solution seems to work for every case I can imagine to try, and do so in well under the 3 second time limit, but when I submit online it still exceeds 3 seconds. I think there must be a case that causes this while loop to go on indefinitely:
while (!equals(availableChars, testChars)){
next = getNextAlphaString(high, next, availableChars, it);
fillCharSet(next, testChars);
}
but I've tested my functions a bunch and I can't figure out what it is...hoping you guys might see something. Here are the helper functions:
bool equals(multiset<char>& availableChars, multiset<char>& test){
multiset<char>::iterator it;
for (it = availableChars.begin(); it != availableChars.end(); it++){
if ((int)availableChars.count(*it) != (int)test.count(*it)) return false;
}
return true;
}
*
string getNextAlphaString(char& high, string next, multiset<char>& availableChars, multiset<char>::iterator& it){
for (int i=next.size()-1; i>=0; i--){
if (next[i] != high){
it = availableChars.find(next[i]);
while(*it == next[i]){
it++;
if (it == availableChars.end()){it = availableChars.begin(); break;}
}
next[i] = *it;
break;}
else{
it = availableChars.begin();
next[i] = *it;
}
}
return next;
}
*
void fillCharSet(string in, multiset<char>& chars){
chars.clear();
for (int i=0; i<in.size(); i++){chars.insert(in[i]);}
}
Here is an article to detect infinite loops using GDB:
http://www.unknownroad.com/rtfm/gdbtut/gdbinfloop.html
Hopefully this will help you with the problem.
Well...here I go answering my own question. I rewrote it with next_permutation, and it was massively easier and more efficient. I still haven't solved the actual looping problem with the other solution, but now I don't need to. Thanks everyone for the tips :)