Matrix out of bounds but can't put condition to check bounds - c++

I have a square matrix, 40 x 40, and a draw circle function that uses this formula.
I have another function that reads input from a file, the point itself (x0, y0) and the type of circle (0 or 1) and the radius.
void cerc(int x0, int y0, int r, int** matriceHarta, int tip, int n, int m)
{
if (r == 0)
return;
int x, y, xx, rr;
for (rr = r * r, x = -r; x <= r; x++)
for (xx = x * x, y = -r; y <= r; y++)
if (xx + (y * y) <= rr && matriceHarta[x0 + x][y0 + y] == 0)
{
if (tip == 0)
matriceHarta[x0 + x][y0 + y] = -5;
else if (tip == 1)
matriceHarta[x0 + x][y0 + y] = -6;
}
}
N and M are the rows and columns, but right now they are both equal.
The matrix is allocated dynamically and is transmitted via the int** matriceHarta parameter.
If I put the point on (39, 39) and I give it the radius 5, the program returns a negative exit code, which I found out is an out of bounds related error. I looked over the for loops and it makes sense that that'd be the error and tried to create the condition if((x0 + x) < n && (y0 + y) < m) to check the bounds, but it still gives the error.
Question is, what am I doing wrong? For contrast, point(37, 4) with radius = 2 is OK, but point(38, 4) with radius = 2 is not OK
This is the attempted fix:
for (rr = r * r, x = -r; x <= r; x++)
for (xx = x * x, y = -r; y <= r; y++)
if (xx + (y * y) <= rr && matriceHarta[x0 + x][y0 + y] == 0
&& (((x0+x) < n) && ((y0+y) < m)) )
//^^^^^ this is the condition i was talking about
{
if (tip == 0)
matriceHarta[x0 + x][y0 + y] = -5;
else if (tip == 1)
matriceHarta[x0 + x][y0 + y] = -6;
}

The issue is that you are testing for the out-of-bounds condition after you have already accessed potential out-of-bounds elements.
Let's break it down into separate lines:
if (xx + (y * y) <= rr && matriceHarta[x0 + x][y0 + y] == 0
&& // <-- This binds the conditions
(((x0+x) < n) && ((y0+y) < m)))
The line above the && marked with <-- is evaluated before the line below the <--.
In summary, the logical && is always evaluated from left-to-right, where the right side will not be evaluated if the left side evaluates to false (short-circuit boolean evaluation).
Thus the fix is to test the bounds condition first (swap the lines in the code above).
However, to make this a little more clear, you could break up the statement into two if statements:
if (x0+x < n && y0+y < m)
{
if (xx + (y * y) <= rr && matriceHarta[x0 + x][y0 + y] == 0)
{
...
}
}

Related

Simplifying a code snippet - vector rotation in a circle

Given the following code pattern, wherein I am trying to state a vector direction in increments of 45 degrees over the integers int x and int y, inside of a circle positioned at the origin
// x == 0 && y == 0 case is already taken cared of
if(x > 1) {
if(y == 0) {
// horizontal right
m_rotation = 0;
}else if(y < 1) {
// diagonal down right
m_rotation = 315;
} else if(y > 1) {
// diagonal up right
m_rotation = 45;
}
} else if(x == 0) {
if(y < 1) {
// vertical down
m_rotation = 270;
} else if(y > 1) {
// vertical up
m_rotation = 90;
}
} else if(x < 1){
if(y == 0) {
// horizontal left
m_rotation = 180;
}else if(y < 1) {
// diagonal down left
m_rotation = 225;
} else if(y > 1) {
// diagonal up left
m_rotation = 135;
}
}
I am looking for an elegant way to make this compact. I know there's the spaceship operator <=>, but I need to restrict myself to C++17.
Things I have tried
Nesting ternary operators with m_rotation = x > 1? (y < 1? (y == 0? 0: 315): 45): (x == 0? (y < 1? 270: 90): (y < 1? (y == 0? 180: 225): 135));, but this looks weird
I tried putting the x == 0 case inside x < 1 case and transform the later into else, but that does not simplify enough the code
Using absolute values to compare x and y, but I quickly get lost
Nothing else really, I don't know what else to try
Something like
constexpr int rotation[3][3] = {
{225, 180, 135},
{270, 0, 90},
{315, 0, 45},
};
if (x != 0 || y != 0) // if (!(x == 0 && y == 0))
m_rotation = rotation[1 + sign(x)][1 + sign(y)];
There is a closed form:
// standard sign functions
int xs = x < 0 ? -1 : x > 0;
int ys = y < 0 ? -1 : y > 0;
return 180 - 45 * (xs + 2) * ys + 90 * (xs * xs + xs) * (ys * ys - 1);
or shorter
return 180 * (x < 0 || y) - 45 * (xs + 2) * ys;

How do i fix this code in random walk problem? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
#include<iostream>
#include<ctime>
#include<cstdlib>
using namespace std;
int main() {
int arr[5][5] = { 0 };
int x =0, y = 0;
int mx,my;
int cnt = 0;
srand(time(NULL));
while(1) {
bool a = true;
int i = rand() % 8;
if (i == 0) {
mx = -1, my = 0;
if ((x + mx) > 4 || (x + mx) < 0 || (y + my) > 4 || (y + my) < 0) continue;
arr[x + mx][y + my] ++;
x += mx;
y += my;
cnt++;
}
if (i == 1) {
mx = 1, my = -1;
if ((x + mx) > 4 || (x + mx) < 0 || (y + my) > 4 || (y + my) < 0) continue;
arr[x + mx][y + my]++;
x += mx;
y += my;
cnt++;
}
if (i == 2) {
mx = 0, my = -1;
if ((x + mx) > 4 || (x + mx) < 0 || (y + my) > 4 || (y + my) < 0) continue;
arr[x + mx][y + my] ++;
x += mx;
y += my;
cnt++;
}
if (i == 3) {
mx = 1, my = 1;
if ((x + mx) > 4 || (x + mx) < 0 || (y + my) > 4 || (y + my) < 0) continue;
arr[x + mx][y + my] ++;
x += mx;
y += my;
cnt++;
}
if (i == 4) {
mx = 1, my = 0;
if ((x + mx) > 4 || (x + mx) < 0 || (y + my) > 4 || (y + my) < 0) continue;
arr[x + mx][y + my] ++;
x += mx;
y += my;
cnt++;
}
if (i == 5) {
mx = 1, my = -1;
if ((x + mx) > 4 || (x + mx) < 0 || (y + my) > 4 || (y + my) < 0) continue;
arr[x + mx][y + my] ++;
x += mx;
y += my;
cnt++;
}
if (i == 6) {
mx = 0, my = -1;
if ((x + mx) > 4 || (x + mx) < 0 || (y + my) > 4 || (y + my) < 0) continue;
arr[x + mx][y + my] ++;
x += mx;
y += my;
cnt++;
}
if (i == 7) {
mx = -1, my = -1;
if ((x + mx) > 4 || (x + mx) < 0 || (y + my) > 4 || (y + my) < 0) continue;
arr[x + mx][y + my]++;
x += mx;
y += my;
cnt++;
}
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 5; j++) {
if (arr[i][j] == 0) a = false;
}
}
if (a == true)break;
}
cout << cnt;
return 0;
}
I'm solving a random walk algorithm problem, but I don't know where it is wrong.
When I compile, nothing is displayed on the black screen.
It was lengthened by not using functions, but I think there is nothing wrong with it.
If there are any parts that can cause errors, please explain
thanks for reading this post i'm waiting your answer
The problem lies in the fact that your various if do not explore all the possible movements you can do given you are in a position x, y. For example, if you see what you do at i == 2
if (i == 2) {
mx = 0, my = -1;
or, at i == 6
if (i == 6) {
mx = 0, my = -1;
you do the same thing. In particular: look at this:
- - V
V X V
V V V
You miss the two movements going up and up-left.
I would review the various if movements (that you save in those two variables, mx and my)
As an improvement to your code, I'd choose a random move only between the ones you can really do.. it would be more clean.

C++ Game of Life infinite looping function

This function in the Game of Life assignment is supposed to loop through the 2nd array and check to see how many neighbors each cell has. When I call this in the main, not even in any sort of loop, the terminal freezes as if in an infinite while loop. Can anyone tell me what's wrong with my code? Thanks.
void Grids::simulate(int** myGrid, int rows, int columns)
{
int neighbors = 0; //variable to store how many neighbors a cell has
for (int r = 0; r < rows; ++r) // iterates through rows
{
for(int c = 0; c < columns; ++c)//iterates through columns
{
for(int x = -1; x < 2; x + 2) //iterates through -1 and 1, the spaces next to the cell
{
for(int y = -1; y < 2; y + 2)
{
if ((r + x >= 0) && (r + x < rows) && (c + y >= 0) && (c + y < columns)) //prevents indexing the 2d array outside of its bounds
{
if (myGrid[r + x][c + y] == 1) //checks if the surrounding cells are alive
{
++neighbors;
}
}
}
}
if (neighbors < 2) //underpopulation
{
myGrid[r][c] = 0; //dead
}
else if (neighbors == 3) //reproduction
{
myGrid[r][c] = 1; //alive
}
else if (neighbors >= 4) //overpopulation
{
myGrid[r][c] = 0; //dead
}
}
}
}
You should change this x + 2 to x += 2 and y + 2 to y += 2, to make the loop increase by 2 each cycle. I also advise you to remove extra parentheses in this line if (r + x >= 0 && r + x < rows && c + y >= 0 && c + y < columns).

how c work in this two cases and what diff

why the result is x=1 y=3 res=1
int x = 7, y = 3;
int res;
res = (x = y < 2 || x != 1);
printf("x = %d y = %d res = %d\n", x, y, res);
and with this code the result is y<2 so False which is 0 so lvalue x = 0 so the res=0
res= (x = y < 2); //|| x != 1);
printf("x = %d y = %d res= %d\n", x, y, res);
res = (x = y < 2 || x != 1);
...is evaluated as...
res = (x = ((y < 2) || (x != 1)));
You can find the Operator Precendence for C++ here - C is similar for the operators you've used.
So for x = 7, y = 3...
res = (x = ((3 < 2) || (7 != 1)));
res = (x = (false || true)); // || is "logical-OR", tests if either true
res = (x = true);
res = (x = 1); // standard conversion from bool to int
res = 1;
For your second, simpler statement:
res = (x = y < 2);
res = (x = (y < 2));
res = (x = (3 < 2));
res = (x = false);
res = (x = 0); // standard conversion from bool false to int 0
res = 0;
In C, even if you #include <stdbool.h> the <, != and || operators will yield 1 immediately for "true" tests, and 0 for "false", and there's no separate "standard conversion" as in C++. Allan's answer describes the C evaluation steps nicely.
res = (x = y < 2 || x != 1);
In above statement y < 2 || x != 1 is a conditional expression whose result is true (1) which is loaded into x.
Now, (x = y < 2 || x != 1) evaluated as x = 1 and hence res = x = 1
This you get res and x equals to 1 and y unchanged.
The issue you seem to be having is operator precedence. The link is to an operator precedence chart which should help clear things up.
First you should know that comparisons result in either a 1 or a 0. For example, (5 < 10) returns 1 because it is true, and (5 > 10) returns 0 because it is false.
In your example, it's easier if we clarify it by adding parenthesis to show the order things are happening in.
res = (x = **(y < 2)** || **(x != 1)**)
This is the first set of operations that happens. After those resolve we are left with:
res = (x = **(0)** || **(1)**)
The next operation to take place is the OR:
res = (x = **(0 || 1)** )
This results in a 1:
res = (x = **1** )
then the assignment operation happens:
res = (**x = 1**)
then the next assignment happens:
**res = x**
Since x is equal to 1 from the previous assignment, res is also set to 1.
Not sure what you're asking in the second bit, so if you want to clarify that I'll answer for you.
< has higher precedence than = and therefore x = y < 2 is equivalent to x = (y < 2).
Since y is greater than 2 therefore y < 2 will give 0 and this value will be assigned to x. Now x is equal to 0 therefore x != 1 will be evaluated as true and the value of the whole expression x = y < 2 || x != will be 1 and this value is assigned to res.
In this case operator precedence will work.
res = (x = y < 2 || x != 1);
In this expression, first y < 2 is evaluated.
Then or(||) will work, because of first condition fails, so now the x is not equal to 1. so the condition will became true so the true value 1 is stored x and in the res variable.
(y < 2 || x != 1 ). // expression is true. So the value 1 is stored in the variable x and ret.
In second case,
y < 2; // this condition will become false. So the zero is stored in both the variable.

Help with this algorithm

I have an algorithm that can find if a point is inside a polygon.
int CGlEngineFunctions::PointInPoly(int npts, float *xp, float *yp, float x, float y)
{
int i, j, c = 0;
for (i = 0, j = npts-1; i < npts; j = i++) {
if ((((yp[i] <= y) && (y < yp[j])) ||
((yp[j] <= y) && (y < yp[i]))) &&
(x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
c = !c;
}
return c;
}
My only issue with it is it assumes an odd winding rule. What I mean by this is that if the polygon is self intersecting, certain parts that it would considered to be 'empty' will return as false. What I'd need in even if it self intersects, anything inside the polygon will return true.
Thanks
Beware: this answer is wrong. I have no time to fix it right now, but see the comments.
This casts a ray from the point to infinity, and checks for intersections with each of the polygon's edges. Each time an intersection is found, the flag c is toggled:
c = !c;
So an even number of intersections means an even number of toggles, so c will be 0 at the end. An odd number of intersections means an odd number of toggles, so c will be 1.
What you want instead is to set the c flag if any intersection occurs:
c = 1;
And for good measure, you can then eliminate c entirely, and terminate early:
int CGlEngineFunctions::PointInPoly(int npts, float *xp, float *yp, float x, float y)
{
int i, j;
for (i = 0, j = npts-1; i < npts; j = i++) {
if ((((yp[i] <= y) && (y < yp[j])) ||
((yp[j] <= y) && (y < yp[i]))) &&
(x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i]))
return 1;
}
return 0;
}
To translate your original algorithm to english: You're determining if the number of polygon segments to the right of your point are even or odd. If it's even (including zero) your point is outside, if it's odd your point is inside. This means if there are two segments to the right and also two segments to the left, the point is not considered inside the polygon.
What you need to do is change the algorithm so that it checks for segments on both sides; if there's a segment on both sides of the point, then the point is within the polygon.
int CGlEngineFunctions::PointInPoly(int npts, float *xp, float *yp, float x, float y)
{
int i, j;
bool hasSegmentLeft = false;
bool hasSegmentRight = false;
for (i = 0, j = npts-1; i < npts; j = i++) {
if ((((yp[i] <= y) && (y < yp[j])) ||
((yp[j] <= y) && (y < yp[i]))))
{
if (x < (xp[j] - xp[i]) * (y - yp[i]) / (yp[j] - yp[i]) + xp[i])
{
hasSegmentRight = true;
if (hasSegmentLeft) // short circuit early return
return true;
}
else
{
hasSegmentLeft = true;
if (hasSegmentRight) // short circuit early return
return true;
}
}
return hasSegmentLeft && hasSegmentRight;
}
P.S. that for statement construct is a very clever way of dealing with a circular list that wraps around to the beginning; I'd never seen it before.