Doing the same thing inside various 'if' statements, can be improved? - c++

I was coding when i faced this problem and i would like to know if this is correct or it can be improved for performance reasons:
if (color == 0) {
if (c.val[0] >= 0 && c.val[0] <= 64) {
//Black
Paint(cursor.x + x, cursor.y + y);
}
}
else if (color == 1) {
if (c.val[0] >= 64 && c.val[0] <= 128) {
//Grey
Paint(cursor.x + x, cursor.y + y);
}
}
else if (color == 2) {
if (c.val[0] >= 128 && c.val[0] <= 192) {
//White Gray
Paint(cursor.x + x, cursor.y + y);
}
}
As you can see im doing the exact same thing inside all IF statements and it looks kind weird, the program works as i want but i really think im missing something..
Thanks!

Because of the structure,
if (color >= 0 && color <= 2) {
if (c.val[0] >= 64*color && c.val[0] <= 64*(color+1)) {
Paint(cursor.x + x, cursor.y + y);
}
}

A few logical operations make it more compact.
if ((color == 0 && c.val[0] >= 0 && c.val[0] <= 64) ||
(color == 1 && c.val[0] >= 64 && c.val[0] <= 128) ||
(color == 2 && c.val[0] >= 128 && c.val[0] <= 192)) {
Paint(cursor.x + x, cursor.y + y);
}

This isn't too terrible with such a short piece of code repeated, but in the interest of Don't Repeat Yourself, and in case more code is needed later, you could simply separate the testing for whether something will be done from the actual doing it, using a flag.
bool need_Paint = false;
if (color == 0) {
// Black?
need_Paint = (c.val[0] >= 0 && c.val[0] <= 64);
}
else if (color == 1) {
// Grey?
need_Paint = (c.val[0] >= 64 && c.val[0] <= 128);
}
else if (color == 2) {
// White Gray?
need_Paint = (c.val[0] >= 128 && c.val[0] <= 192);
}
if (need_Paint)
Paint(cursor.x + x, cursor.y + y);
(Note a compiler's optimizations can possibly handle this sort of thing without actually putting a bool in memory, just jumping to the function call statement if the appropriate condition is true.)
(This also looks like the sort of pattern often written as a switch. You could consider using that syntax instead of all the ifs.)
But in fact this particular code can get even simpler, because there's a straightforward mathematical pattern to the three different tests you're doing:
if (color >= 0 && color <= 2 && // (if these aren't already guaranteed)
c.val[0] >= 64*color && c.val[0] <= 64*(color+1)) {
Paint(cursor.x + x, cursor.y + y);
}
(Another thing to consider might be using enum ColorType { BLACK=0, GREY=1, WHITE_GRAY=2 }; instead of just writing the "magic numbers" 0, 1, and 2 directly. But if you use both an enum and the mathematical version of this code, I'd recommend you specify the exact values as shown, even though the default for an enum is always consecutive counting from zero, to make it clear you're counting on those values.)

I like your original post more than the selection.
Here is a another approach with about the same number of lines ... but I find more readable.
void yourSnippet() {
switch (color) {
case 0: { PaintIf( 0, 64); } break; // black
case 1: { PaintIf( 64, 128); } break; // Grey
case 2: { PaintIf(128, 192); } break; // White Gray
} // switch
}
void PaintIf(int min, int max) {
if ((c.val[0] >= min) && (c.val[0] <= max))
Paint(cursor.x + x, cursor.y + y);
}

Another solution that closely follows the lines of 2785528's answer but uses a lambda to avoid passing additional arguments to PaintIf:
const auto PaintIf = [&](int min, int max)
{
if (min <= c.val[0] && c.val[0] <= max)
Paint(cursor.x + x, cursor.y + y);
};
switch (color)
{
case 0: PaintIf( 0, 64); break;
case 1: PaintIf( 64, 128); break;
case 2: PaintIf(128, 192);
}

Lambdas are (as of c++17) guaranteed to be constexpr (i.e. zero cost abstractions) if possible.
They can sometimes allow more succinct and maintainable expressions of logic:
auto range = [](int color)
{
auto min = color * 64;
auto max = min + 64;
return std::make_tuple(min, max);
};
auto in_range = [](auto val, auto tuple)
{
auto [min, max] = tuple;
return val >= min && val <= max;
};
if (in_range(c.val[0], range(color)))
Paint(cursor.x + x, cursor.y + y);

Related

How to make a loop to determine if 2 numbers belong in a given range

I am having problems making a loop which stops when both x and y are in the range/interval [0,1] in c++.
double x;
double y;
while(condition)
{
if(x < 0)
{
x = -x;
}
else
{
x = 2 - x;
}
if(y < 0)
{
y = -y;
}
else
{
y = 2 - y;
}
}
This method with 2 loops works:
while((x < 0) || (x > 1)) {do sth}
while((y < 0) || (y > 1)) {do sth}
This doesn't work:
while(!((x >= 0) && (x <= 1)) && !((y >= 0) && (y <= 1))) {do sth}
And this doesn't work either:
while(((x < 0) || (x > 1)) && ((y < 0) || (y > 1))) {do sth}
This makes an infinite loop (in my case):
while(((x < 0) || (x > 1)) || ((y < 0) || (y > 1))) {do sth}
Note: {do sth} changes x and y if needed so they will eventually go in that interval (same as in the first block of code).
Note 2: By doesn't work I mean it never goes in the loop when x is in the interval and y < 0 (and some other cases).
while ( !( (x>=0 && x<=1) && (y>=0 && y<=1) ) ) should be the combined conditional check.
I'd go for a dedicated function with a speaking name: so you can still understand your code in a couple of weeks :-), e.g.
auto check_outside_interval_0_1 = [] (double const a) {
return a < 0.0 or 1.0 < a;
};
while( check_outside_interval_0_1(x) or
check_outside_interval_0_1(y) ) {
// ... do your things here
}

How do I check the neighbors of the cells around me in a 2D array (C++)?

So I'm trying to check if the cells surrounding the current cell of any given 2D array have a certain value (0 or 1) and depending on the value I want to count the total amount (total 1 values surrounding the current cell) however I'm not sure how to grab the positions below is some psuedocode I wrote that I think will consider each general position for a cell to be in however I'm not completely certain it is correct, and if it is correct I'm not sure how to grab the surrounding cells. Its not necessary to write out the whole code but basically I'm looking for conditions for positions to check for in future nested if statements that will of these big if statements such as array
if array([xPosition+1][yPosition+1] == 1)
Here is the pesudocode
if (xPosition==0 && yPosition==0) {
} else if (xPosition==rows && yPosition==columns) {
} else if (xPosition==rows && yPosition==0) {
} else if (xPosition==0 && yPosition==columns) {
} else if (xPosition==0) {
} else if (xPosition==rows) {
} else if (yPosition==0) {
} else if (yPosition==columns) {
} else {
}
You can use nested loops
int sum{0};
for (int x{std::max(xPosition, 1) - 1}; x < std::min(xPosition + 2, columns); ++x) {
for (int y{std::max(yPosition, 1) - 1}; y < std::min(xPosition + 2, rows); ++y) {
if (x == xPosition && y == yPosition) continue;
sum += array[x][y];
}
}
The code is self explanatory and I have added the comments
bool isSafe(int xPosition, int yPosition,
int rows, int columns) { // checking the boundry
return (xPosition >= 0 && xPosition < rows &&
yPosition >= 0 && yPosition < columns);
}
void checkNeighbours(int xPosition, int yPosition,
int rows, int columns) {
// Considering only 4 directions up, down , right, left
int count = 0;
if(isSafe(xPosition - 1, yPosition)) { // one cell up
if(array[xPosition - 1][yPosition] == 1) {
count ++;
}
}
if(isSafe (xPosition + 1, yPosition)) { // one cell down
if(array[xPosition + 1][yPosition] == 1) {
count ++;
}
}
if(isSafe(xPosition, yPosition - 1)) { // one cell left
if(array[xPosition][yPosition - 1] == 1) {
count ++;
}
}
if(isSafe(xPosition, yPosition + 1)) { // one cell right
if(array[xPosition][yPosition + 1] == 1) {
count ++;
}
}
// use count for whatever
}

Counting total Paths from (0,0) to (n-1,n-1) in a n*n grid

I am using a simple backtracking algorithm to find all the paths but it does not give the right answer. I am not able to figure out the mistake. We can move up, down, left and right from a given position.
Int path(int a[][200],int n,int m,int r,int c)
{
if(n == r - 1 && m == c-1) {
return 1;
}
else if(n >= r || m >= c || n < 0 || m < 0) {
return 0;
}
else if(vis[n][m] == 1) {
return 0;
}
else {
vis[n][m] = 1;
int x = path(a,n+1,m,r,c);
int y = path(a,n,m+1,r,c);
int u = path(a,n-1,m,r,c);
int v = path(a,n,m-1,r,c);
vis[n][m] = 0;
return (x+y+u+v);
}
}
To find the paths or count the paths are not exactly the same thing. I will assume you want to just count the paths (because the title of your question), and that you can only move right or move down.
For this you don't really need a matrix (representing the grid) as a parameter. The following is a simple (although not efficient) recursive solution that also will work for a n*m grid:
int countPaths(int m, int n) {
if (m == 0 || n == 0)
return 1;
return countPaths(m-1, n) + countPaths(m, n-1);
}
The mathematical solution for the general n*n grid is:
(2n choose n) = (2*n)!/(n!*n!)
Then, comparing results with the formula:
countPaths(1, 1) == 2 // (2*1)!/(1!*1!)=2
countPaths(2, 2) == 6 // (2*2)!/(2!*2!)=6
countPaths(3, 3) == 20 // (2*3)!/(3!*3!)=20
Your backtracking approach will give the same results, but with some considerations. For example, consider when n=2, you will need a 3x3 matrix (and in general a (n+1)x(n+1) matrix) to represent/explore (and mark with 1) all the paths for the 2x2 grid:
int countPaths(int a[][3],int n, int m, int r, int c) {
if(n == r-1 && m == c-1) {
return 1;
}
else if(n >= r || m >= c || n < 0 || m < 0) {
return 0;
}
else if(vis[n][m] == 1) {
return 0;
}
else {
vis[n][m] = 1;
int x = countPaths(a,n+1,m,r,c);
int y = countPaths(a,n,m+1,r,c);
vis[n][m] = 0;
return (x+y);
}
}
Then:
countPaths(vis, 0, 0, 3, 3) == 6 // (2*2)!/(2!*2!)=6

Is there a better way of selecting a random element from an array of variable size than this?

I'm very new to C++ and was wondering if if there is a better way of doing this. It's going to run on an Arduino so I can't use ArrayLists or anything.
byte GetFreeCell(short x, short y)
{
byte possibleMoves[4] = {0,0,0,0};
if (y - 2 >= 0 && _grid[y - 2][x] == 0)
possibleMoves[0] = 1;
if (x + 2 < WIDTH && _grid[y][x + 2] == 0)
possibleMoves[1] = 2;
if (y + 2 < HEIGHT && _grid[y + 2][x] == 0)
possibleMoves[2] = 3;
if (x - 2 >= 0 && _grid[y][x - 2] == 0)
possibleMoves[3] = 4;
if (possibleMoves[0] == 0 && possibleMoves[1] == 0 && possibleMoves[2] == 0 && possibleMoves[3] == 0) {
return 0;
}
byte move = 0;
while(move == 0){
move = possibleMoves[random(4)];
}
return move;
}
Thanks,
Joe
byte GetFreeCell(short x, short y)
{
byte possibleMoves[4];
byte index = 0;
if (y - 2 >= 0 && _grid[y - 2][x] == 0)
possibleMoves[index++] = 1;
if (x + 2 < WIDTH && _grid[y][x + 2] == 0)
possibleMoves[index++] = 2;
if (y + 2 < HEIGHT && _grid[y + 2][x] == 0)
possibleMoves[index++] = 3;
if (x - 2 >= 0 && _grid[y][x - 2] == 0)
possibleMoves[index++] = 4;
return index ? possibleMoves[random(index)] : 0;
}
You can do yourself a favor and use this:
https://github.com/maniacbug/StandardCplusplus/#readme
Then you can sanitize your code by using standard containers.
Also, there's no ArrayList in C++. That's Java. With the above library, you can use std::vector instead.

Best way to format the conditional checks in "if" statement

This code looks dirty and I can't figure out how to format it so that I can read it, understand it, and look clean at the same time.
if(center==2 && ((((y-height/2)==j) && ((x+width/2)==i)) || (((y+height/2)==j) && ((x+width/2)==i))))
regenerateDot(i+1, j, dots);
Any suggestions?
I would break down the boolean expressions into variables named for readability. Something like:
bool isCentered = center == 2;
bool inLowerRegion = (y-height/2) == j && (x+width/2) == i;
bool inUpperRegion = (y+height/2) == j && (x+width/2) == i;
bool inEitherRegion = inLowerRegion || inUpperRegion;
if (isCentered && inEitherRegion) {
regenerateDot(i+1, j, dots);
}
Consider refactoring. You could put sub expressions into their own functions, thus naming their purpose.
For example:
if (IsCentered(center) && IsInsideLower(y, j, i) && IsInsideUpper(y, j, i))
regenerateDot(i + 1, j, dots);
Note that in the above example the function names might be bogus (I haven't really attempted to understand what the purpose of the code is), but you should get the picture.
Almost all the parenthesis are redundant... and adding some whitespace it becomes:
if(center == 2 &&
(y - height/2 == j && x + width/2 == i ||
y + height/2 == j && x + width/2 == i))
regenerateDot(i+1, j, dots);
For something complicated I'd probably break it down into what each condition (grouped by shared &&) is trying to signify and assign it to a sensible variable name.
At most you can remove extra braces, add some spaces and put the logical partitions in different lines as,
if(center == 2 &&
(((y - height/2) == j || (y + height/2) == j) && (x + width/2) == i))
{
regenerateDot(i+1, j, dots);
}
Edit: You have one redundant condition (x + width/2) == i which I have optimized here.
This is the same as the code you posted:
if( center == 2 )
{
if( (x+width/2) == i )
{
if( (y-height/2) == j ) || (y+height/2) == j ) )
{
regenerateDot(i+1, j, dots);
}
}
}
Re-ordering it would give something like :
if (center==2 && (i-x)==(width/2) && abs(j-y)==(height/2))
regenerateDot(i+1, j, dots);
I would do it like this
if (2 == center &&
(((y - height/2) == j && (x + width/2) == i) ||
((y + height/2) == j && (x + width/2) == i))
)
{
regenerateDot(i + 1, j, dots);
}