Check if C-style array equals other (compile-time) array - c++

I've got a double[9] and want to check if it contains the values (1,0,0,0,1,0,0,0,1). Is there a cleaner way than this?
if (ornt1[0] == 1 && ornt1[1] == 0 && ornt1[2] == 0
&& ornt1[3] == 0 && ornt1[4] == 1 && ornt1[5] == 0
&& ornt1[6] == 0 && ornt1[7] == 0 && ornt1[8] == 1 )
I'm using C++.

It is not a good idea to compare double values strictly. I would recommend you create a constant array to compare against and then use a cycle and also use a tolerance(e.g. 1e-9):
bool doublesEqual(double a, double b) {
return fabs(a - b) < 1e-9;
}
const double expected[9] = {1,0,0,0,1, 0, 0, 0, 1};
bool equal = true;
for (int i = 0; i< 9; ++i) {
if (!doublesEqual(expected[i], ornt1[i])) {
equal = false;
break;
}
}
if (equal) { // do smth
EDIT: as suggested by John Zwinck I have edited the code to be able to handle the case when the array we compare contains only NAN. I have edited his suggestion a bit to make the code more readable. Please refer to his comment below for clarification why this is needed.

Related

Issues with commutative property of && operator

The code below that I have been having strange issues with is meant to trim off the unused portion of an integer array, and then convert it into a string.
Ex:
_ABC__DE______ would become _ABC__DE.
The problems show up when the input is filled with the default character. ("_" in the example).
sLength is the length of the integer array chars
The problematic code:
int inputLength = sLength - 1;
while (chars[inputLength] == defaultChar && inputLength >= 0) {
inputLength--;
}
inputLength++;
Serial.println("input length: " + String(inputLength));
// (in)sanity check
Serial.println(inputLength);
Serial.println(String(inputLength));
Serial.println(inputLength <= 0);
Serial.println(0 <= 0);
Serial.println(inputLength == 0);
Serial.println(0 == 0);
if (inputLength <= 0) {
//reset cursor position
Serial.println("index set to 0");
index = 0;
} else {
output = "";
for (int i = 0; i < inputLength; i++) {
char c = charSet[chars[i]];
if (c == '_') {
c = ' ';
}
output += c;
}
done = true;
}
The output when given an array filled with defaultChar:
input length: 0
0
0
0
1
0
1
If I'm interpreting correctly, the output means that 0 > 0 and 0 =/= 0 on even lines, but 0 <= 0 and 0 = 0 on odd lines.
The workaround I've come up with is replacing
while (chars[inputLength] == defaultChar && inputLength >= 0) {
inputLength--;
}
with one of the following
while (inputLength >= 0 && chars[inputLength] == defaultChar) {
inputLength--;
}
.
while (chars[inputLength] == defaultChar) {
inputLength--;
if (inputLength < 0) {
break;
}
}
which both result in an output of:
input length: 0
0
0
1
1
1
1
index set to 0
Why does this change the result?
As far as I knew until now, the && operator was commutative.
Is there something that I am missing that makes
chars[inputLength] == defaultChar && inputLength >= 0
not equal to
inputLength >= 0 && chars[inputLength] == defaultChar?
If It's relevant, this is being run on an 328P Arduino Nano with the old bootloader using IDE 1.8.8
&& is not commutative. It evaluates the left operand first and then stops if the left operand evaluated to 0.
Your original code fails because at some point it evaluates chars[-1] (which causes undefined behaviour if chars is an array). The alternative version does not have that problem because it performs the >= 0 test before using inputLength as an array index.
&& is commutative in the sense that the result of a && b is same as the result of b && a. But the built-in operator && has a short-circuiting behavior. This means that if the result of a && b can be decided by evaluating the first operand alone, the second one is not evaluated.
So when the first operand is chars[inputLength] == defaultChar and inputLength is -1, you enter the territory of undefined behavior which means the behavior of the program is unpredictable. But with the workarounds, you avoid undefined behavior because of the inputLength >= 0 and inputLength < 0 checks and therefore the code works as intended.
As #PeteBecker notes: a() && b() is not commutative if either a() or b() has side effects.

Find if path exist or not in maze c++

My code is giving me runtime error. I can't figure it out how to resolve it?
It's not even working for smaller matrix 4 X 4 . Matrix size for the problem is not more than 20 x 20.
Code:
#include <iostream>
using namespace std;
int a[20][20];
bool findpath(int ar[][20],int i,int j,int size)
{
if (ar[i][j]==0 || i>(size-1) || j>(size-1) || i<0 || j<0)
return false;
if (ar[i][j]==2)
return true;
if ((findpath(ar,i+1,j,size)) || (findpath(ar,i,j+1,size))
|| (findpath(ar,i-1,j,size)) || (findpath(ar,i,j-1,size)))
return true;
return false;
}
int main() {
int t;
cin>>t;
while(t--)
{ int n;
cin>>n;
int r,c;
//size = n;
for(int i =0 ;i<n;i++)
{
for(int j=0;j<n;j++)
{
cin>>a[i][j];
if (a[i][j]==1)
{ r=i;
c=j;
}
}
}
//cout<<r<<c;
bool b = findpath(a,r,c,n);
if (b)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
}
return 0;
}
Input:
1
4
3 0 0 0 0 3 3 0 0 1 0 3 0 2 3 3
Output:
YES
But I am getting Segmentation Fault (SIGSEGV)
Check the order of evaluation of your statement if (ar[i][j]==0 || i>(size-1) || j>(size-1) || i<0 || j<0). You will access ar[i][j] to evaluate the first expression even if i is out of bounds or j is out of bounds. It should be in the order so that when a short circuit does happen in the if condition you are safe/does not result in undefined behaviour for example:
if (i < 0 || i >= size || j < 0 || j >= size || ar[i][j]==0). Now if i < 0 it shorcircuits and does not need to check the rest and does not evaluate ar[i][j].
As you mentioned this is not working, here is a working version which I will explain. First I have changed your C style arrays to vectors and rather I use those to get row and col sizes. I also removed your inputs from users which you can add in later and helps keep the problem simple.
#include <vector>
bool findpath(vector<vector<int>>ar,int i,int j,vector<vector<int>>& visited)
{
if (i < 0 || i >= ar.size() || j < 0 || j >= ar[0].size() || ar[i][j] == 0 || visited[i][j]) return false;
if (ar[i][j]==2) return true;
visited[i][j] = true;
if(findpath(ar,i+1,j,visited) || findpath(ar,i,j+1,visited) || findpath(ar,i-1,j,visited) || findpath(ar,i,j-1,visited)) return true;
visited[i][j] = false;
return false;
}
int main() {
const int rows = 3;
const int cols = 3;
vector<vector<int>> arr = {{ 0 , 3 , 2 },
{ 3 , 3 , 0 },
{ 1 , 3 , 0 }};
vector<vector<int>> visited(rows,vector<int>(cols,false));
bool b = findpath(arr,1,1,visited);
if (b)
cout<<"YES"<<endl;
else
cout<<"NO"<<endl;
return 0;
}
In the main function I have just used a vector<vector<int>> to describe a maze which was in the link you posted. The i and j are the starting points in the example below that is 1 and 1. There is also a visited 2D array same as the maze. This stops you from going in an infinite recursion by marking the spots you have already covered and if they dont work out you set vector[i][j] = false to backtrack. Lastly if any of your arrangements returns a valid result we return else we just return false.
You can view this demo live here
You also mention that 1 is the starting point. In the example I have already started from 1. You can add a loop in main to first figure out the coordinates for the starting point. Again this should be enough to get you going.

Is it possible to consolidate my If statements here?

I am developing an 8x8 grid game. Similar to checkers I guess. Players can move in any direction and jump/take a piece in any direction.
I am individually writing out EVERY single move.. including invalid moves. Is there a way for me to clean this up? I believe there is but I just dont see it at the moment, I cant seem to think up a simpler solution.
Everything works fine, I just am curious if its possible to shorten it.
Heres some of the moves:
//If player attempts to move 2 squares within the same column
if(checkRow == 2 && checkCol == 0){
//Checks if row is OOB. If not, Checks to see if there is a player 2 one position to the right.
//If yes checks to see if row - 2 equals the initial player. This avoids methods getting called
// When surrounded by multiple pieces.
if(fromRow+1 < 8 && boardGame[fromRow+1][fromCol].getPlayer()== 2 && boardGame[toRow-2][toCol].getPlayer() == 1){
board[fromRow+1][fromCol] = 0;
valid = true;
updateTurnCount();
}
//Checks if row is OOB. If not, Checks to see if there is a player 2 one position to the left.
else if(fromRow-1 >= 0 && boardGame[fromRow-1][fromCol].getPlayer()== 2 && boardGame[toRow+2][toCol].getPlayer() == 1){
board[fromRow-1][fromCol] = 0;
valid = true;
updateTurnCount();
}
else if(fromRow+1 < 8 && boardGame[fromRow+1][fromCol].getPlayer()== 1 && boardGame[toRow-2][toCol].getPlayer() == 2){
board[fromRow+1][fromCol] = 0;
valid = true;
updateTurnCount();
}
else if(fromRow-1 >= 0 && boardGame[fromRow-1][fromCol].getPlayer()== 1 && boardGame[toRow+2][toCol].getPlayer() == 2){
board[fromRow-1][fromCol] = 0;
valid = true;
updateTurnCount();
}
}
Don't quite get what your asking here but you can certainly pull most of this logic out into simple statements that will cover all cases.
if ( newRow <0 || newRow >8 ) {
disallowMove();
return;
}
if ( board[newRow][newCol].player() != board[oldRow][oldCol].player() ){
disallowMove();
return;
}
board[newRow][newCol] == somethingElse;
updateTurnCount();
lambdas can shorten considerably the code: for instance, declaring just immediately before the main loop
auto from = [boardGame,fromRow,fromCol](int deltaRow, int deltaCol) {
return boardGame[fromRow+deltaRow][fromCol+deltaCol];
};
auto to = [boardGame,toRow,toCol](int deltaRow, int deltaCol) {
return boardGame[toRow+deltaRow][toCol+deltaCol];
};
the conditions can be written like
if(fromRow+1 < 8 && from(+1,0) == 2 && to(-2,0) == 1){...}
Further cleanup can follow from factorization of repeated code: the action taken is always the same, and uses the same variables pattern: then the lambda (assuming boardGame etc are member variables) could be
auto action = [this](int df_Row, int df_Col, int dt_Row, int dt_Col) {
int f_row = fromRow+deltaRow, f_col = fromCol+deltaCol;
int t_row = toRow+dt_Row, t_col = toCol+dt_Col;
if (f_row < 8 && boardGame[f_row][f_col].getPlayer()== 2 &&
boardGame[t_row][t_col].getPlayer() == 1){
boardGame[f_row][f_col] = 0;
valid = true;
return true;
}
return false;
};
and the logic become simpler:
if (action(+1,0,-2,0)) updateTurnCount();
...

Passing a 2D array through a function and I get an error

I am making a recursive algorithm as part of an extra credit project for class to find the shortest path through a 2D int array maze of 0's and 1's. 0 represents a wall and 1 represents a hallway where you can pass through. I think I have everything perfect but it just won't compile. It says I am trying to convert something from int to array or whatever. Here is my code, please help.
#include <iostream>
using namespace std;
#define 20 SIZEX;
#define 5 SIZEY;
int value; //to compare paths to take
int starti = 1;
int startj = 0;
int newi;
int newj;
int counter = 0; //keeps track of how many steps taken
void pathfinder(int a[][SIZEX], int currenti, int currentj);
int arr[SIZEY][SIZEX] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,
0,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int main()
{
pathfinder(arr, starti, startj);
system("PAUSE");
return 0;
}
void pathfinder(int a[][SIZEX], int currenti, int currentj)
{
//as soon as it walks somewhere, the value of that spot increments
int temp;
temp = a[currenti][currentj];
temp++;
a[currenti][currentj] = temp;
if (counter == 0) //keeps track of starting point
{
starti = currenti;
startj = currentj;
}
if (currenti-1 >= 0 && a[currenti-1][currentj] != 0) //checks up
{
value = a[currenti-1][currentj];
}
else if (currenti+1 < 5 && a[currenti+1][currentj] != 0) //checks down
{
value = a[currenti+1][currentj];
}
else if (currentj-1 >= 0 && a[currenti][currentj-1] != 0) //checks left
{
value = a[currenti][currentj-1];
}
else if (currentj+1 < 20 && a[currenti][currentj+1] != 0) //checks right
{
value = a[currenti][currentj+1];
}
//value has a value, now check it against all possible values for the least travelled path
if ((currenti-1 >= 0 && a[currenti-1][currentj] !=0) && value > a[currenti-1][currentj])
{
value = a[currenti-1][currentj];
}
if ((currenti+1 < 5 && a[currenti+1][currentj] !=0) && value > a[currenti+1][currentj])
{
value = a[currenti+1][currentj];
}
if ((currentj-1 >= 0 && a[currenti][currentj-1] != 0) && value > a[currenti][currentj-1])
{
value = a[currenti][currentj-1];
}
if ((currentj+1 < 20 && a[currenti][currentj+1] != 0) && value > a[currenti][currentj+1])
{
value = a[currenti][currentj+1];
}
//value now holds the smallest possible value among the four possible paths
if ((currenti-1 >= 0 && a[currenti-1][currentj] !=0) && value == a[currenti-1][currentj]) //move up
{
newi = currenti-1;
newj = currentj;
counter++;
}
else if ((currenti+1 < 5 && a[currenti+1][currentj] !=0) && value == a[currenti+1][currentj]) //move down
{
newi = currenti+1;
newj = currentj;
counter++;
}
else if ((currentj-1 >= 0 && a[currenti][currentj-1] != 0) && value == a[currenti][currentj-1]) //move left
{
newi = currenti;
newj = currentj-1;
counter++;
}
else if ((currentj+1 < 20 && a[currenti][currentj+1] != 0) && value == a[currenti][currentj+1]) //move right
{
newi = currenti;
newj = currentj+1;
counter++;
}
//upon reaching the exit, it will print out a new 2d maze, and the path with the smallest value of non-zero integers is the shortest path
if ((currenti == 0 || currentj == 0 || currenti == 4 || currentj == 19) && (currenti != starti || currentj !=startj))
{
for (int i = 0; i < 5; i++)
{
for (int j = 0;j < 20;j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
return;
}
pathfinder(arr, newi, newj);
}
1>------ Build started: Project: Project5, Configuration: Debug Win32
------ 1> Source.cpp 1>c:\users\justin\documents\visual studio 2012\projects\project5\project5\source.cpp(22): error C2664:
'pathfinder' : cannot convert parameter 1 from 'int' to 'int [][20]'
1> Conversion from integral type to pointer type requires
reinterpret_cast, C-style cast or function-style cast
1>c:\users\justin\documents\visual studio
2012\projects\project5\project5\source.cpp(114): error C2664:
'pathfinder' : cannot convert parameter 1 from 'int' to 'int [][20]'
1> Conversion from integral type to pointer type requires
reinterpret_cast, C-style cast or function-style cast
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
These are incorrect:
#define 20 SIZEX;
#define 5 SIZEY;
If you really want macros, the correct way to define them is:
#define SIZEX 20
#define SIZEY 5
But, as this is C++, you should make use of const int here:
const int SIZEX = 20;
const int SIZEY = 5;
That should fix your compile problem.
On a separate note: If you're going to pass arr as your initial argument to pathfinder() to start the recursion in main, you might change your recursive call to pass the argument pathfinder() was passed. ie:
pathfinder(a, newi, newj);
Otherwise, even if main were to pass a different array to pathfinder, it would still do most of its work on arr, rendering the parameter useless.

How to combine two if statements into one

Hi I have these two separate if statements, when put like so ;
if (powerlevel <= 0) // <--- ends up having no effect
if (src.health <= 0)
the_thing_to_do();
How do I combine these two if statements into one? is it possible? If so how?
If you want both statements to be true use logical AND
if(powerlevel <= 0 && src.health <= 0)
If you want either of the statements to be true use logical OR
if(powerlevel <= 0 || src.health <= 0)
Both of the above operators are logical operators
Use operator&& if you want both of them to be met (logical AND)
if(powerlevel <= 0 && src.health <= 0) { .. }
or operator|| if you want just one to be met (logical OR)
if(powerlevel <= 0 || src.health <= 0) { .. }
It depends if you want both to evaluate to true...
if ((powerlevel <= 0) && (src.health <= 0)) {
// do stuff
}
... or at least one ...
if ((powerlevel <= 0) || (src.health <= 0)) {
// do stuff
}
The difference being logical AND (&&) or logical OR (||)
Just an aternative if it is meaningful(sometimes).
Both true:
if (!(src.health > 0 || powerlevel > 0)) {}
at least one is true:
if (!(src.health > 0 && powerlevel > 0)) {}
Or if you don't want to use && you can use a Ternary Operator
#include <iostream>
int main (int argc, char* argv[])
{
struct
{
int health;
} src;
int powerlevel = 1;
src.health = 1;
bool result((powerlevel <= 0) ? ((src.health <=0) ? true : false) : false);
std::cout << "Result: " << result << std::endl;
}