Using C language, I wrote a code that gives me the eight nearest neighbors of a "site" or entry in a 2d array. The problem is that when I select an entry located on edge, I cannot obtain the correct neighbor considering the periodic boundary conditions.
The following code works perfectly when I choose an entry outside the edges:
First the program asks the user to enter the coordinates of the matrix entry, then it finds eight nearest neighbors.
//Code:
#define XMAX 3
#define YMAX 3
#define LOWER 0
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main( )
{
int count = 1;
int number;
int x=0,y=0;
int right, left, up, down, upleft, upright, downleft, downright;
int grid[XMAX][YMAX];
//Printing the matrix
for (int i = 0; i < XMAX ; i++) {
for (int j = 0; j < YMAX; j++) {
grid[i][j] = count++;
printf("%d ", grid[i][j]);
}
printf("\n");
}
//Here I ask the user to enter the coordinates of the entry
printf("\nEnter a X-coordinate :\n");
scanf("%d", &y);
printf("\nEnter a Y-coordinate :\n");
scanf("%d", &x);
printf("(x,y)=(%d,%d)\n",y,x); //print the chosen coordinates
//Locating the entry of te matrix given the prior coordinates
for (int i = 0; i < XMAX; i++)
{
for (int j = 0; j < YMAX; j++ )
{
if(x == i && y == j){ grid[x][y] == count; }
}
}
//Looking up the nearest 8 neighbors (If the chosen entry is not on any edge of the matrix)
right = grid[y][x+1];
left = grid[y][x-1];
up = grid[y-1][x];
down = grid[y+1][x];
upleft = grid[y-1][x-1];
upright = grid[y-1][x+1];
downleft = grid[y+1][x-1];
downright = grid[y+1][x+1];
//Considering periodic boundary conditions for the right neighbor
if (grid[y][x] == grid[YMAX-1][x]){
right = grid[0][x];
}
printf("The coordinates are (%d,%d) and the solicited matrix entry is: %d\n", y, x, grid[y][x]);
//Printing the eight nearest neighbors
printf("Right: %d\nLeft: %d\nUp: %d\nDown: %d\nUpleft: %d\nUpright: %d\nDownleft: %d\nDownright: %d\n",right,left,up,down,upleft,upright,downleft,downright);
return 0;
}
However when the user enters an entry located at the right edge, for example, the problem doesn't give the proper neighbor. The part of the code that should do this is:
if (grid[y][x] == grid[YMAX-1][x]){
right = grid[0][x];
}
But it seems the program never passes through this part of the code. I don't know what to do with this problem. Could you help me with that, please?
A very first change I would suggest is to avoid assigning x
given by the user to a variable called y
. Better keep the same name. So x
is the column coordinate and y
is the row coordinate, such as the notation used in math matrices.
After this I think the biggest problem is the part the assigns the neighbor values. For instance, this:
right = grid[y][x+1];
Will go out of bounds of grid
matrix when x + 1 >= XMAX
Similarly, when x-1 < 0
, this part:
left = grid[y][x-1];
Will try to access a negative index which is invalid.
You can follow the suggestion given in a question comment to address this by using modulo or possibly creating a macro. At first I would suggest writing a simple function to handle this, such:
int get_limited_coord(int coord, int coord_max)
{
if (coord >= 0 && coord < coord_max) {
return coord;
} else if (coord >= coord_max) {
return coord - coord_max;
} else {
return coord + coord_max;
}
}
And then the block that assigns these values becomes:
right = grid[get_limited_coord(y , YMAX)][get_limited_coord(x+1, XMAX)];
left = grid[get_limited_coord(y , YMAX)][get_limited_coord(x-1, XMAX)];
up = grid[get_limited_coord(y-1, YMAX)][get_limited_coord(x , XMAX)];
down = grid[get_limited_coord(y+1, YMAX)][get_limited_coord(x , XMAX)];
upleft = grid[get_limited_coord(y-1, YMAX)][get_limited_coord(x-1, XMAX)];
upright = grid[get_limited_coord(y-1, YMAX)][get_limited_coord(x+1, XMAX)];
downleft = grid[get_limited_coord(y+1, YMAX)][get_limited_coord(x-1, XMAX)];
downright = grid[get_limited_coord(y+1, YMAX)][get_limited_coord(x+1, XMAX)];
Would remove this block which does not seem to do anything now:
//Locating the entry of te matrix given the prior coordinates
for (int i = 0; i < XMAX; i++)
{
for (int j = 0; j < YMAX; j++ )
{
if(x == i && y == j){ grid[x][y] == count; }
}
}
And ensure user input is valid:
if (x >= XMAX || x < 0 || y >= YMAX || y < 0) {
printf ("Invalid coordinates given\n");
return 1;
}
Here's the code with these changes:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define XMAX 3
#define YMAX 3
#define LOWER 0
int get_limited_coord(int coord, int coord_max)
{
if (coord >= 0 && coord < coord_max) {
return coord;
} else if (coord >= coord_max) {
return coord - coord_max;
} else {
return coord + coord_max;
}
}
int main( )
{
int count = 1;
int number;
int x=0,y=0;
int right, left, up, down, upleft, upright, downleft, downright;
int grid[XMAX][YMAX];
//Printing the matrix
for (y = 0; y < XMAX ; y++) {
for (x = 0; x < YMAX; x++) {
grid[y][x] = count++;
printf("%d ", grid[y][x]);
}
printf("\n");
}
//Here I ask the user to enter the coordinates of the entry
printf("\nEnter a X-coordinate :\n");
scanf("%d", &x);
printf("\nEnter a Y-coordinate :\n");
scanf("%d", &y);
printf("(x,y)=(%d,%d)\n",x,y); //print the chosen coordinates
if (x >= XMAX || x < 0 || y >= YMAX || y < 0) {
printf ("Invalid coordinates given\n");
return 1;
}
//Looking up the nearest 8 neighbors (If the chosen entry is not on any edge of the matrix)
right = grid[get_limited_coord(y , YMAX)][get_limited_coord(x+1, XMAX)];
left = grid[get_limited_coord(y , YMAX)][get_limited_coord(x-1, XMAX)];
up = grid[get_limited_coord(y-1, YMAX)][get_limited_coord(x , XMAX)];
down = grid[get_limited_coord(y+1, YMAX)][get_limited_coord(x , XMAX)];
upleft = grid[get_limited_coord(y-1, YMAX)][get_limited_coord(x-1, XMAX)];
upright = grid[get_limited_coord(y-1, YMAX)][get_limited_coord(x+1, XMAX)];
downleft = grid[get_limited_coord(y+1, YMAX)][get_limited_coord(x-1, XMAX)];
downright = grid[get_limited_coord(y+1, YMAX)][get_limited_coord(x+1, XMAX)];
printf("The coordinates are (%d,%d) and the solicited matrix entry is: %d\n", y, x, grid[y][x]);
//Printing the eight nearest neighbors
printf("Right: %d\nLeft: %d\nUp: %d\nDown: %d\nUpleft: %d\nUpright: %d\nDownleft: %d\nDownright: %d\n",right,left,up,down,upleft,upright,downleft,downright);
return 0;
}
And a simple test:
$ ./a.out
1 2 3
4 5 6
7 8 9
Enter a X-coordinate :
0
Enter a Y-coordinate :
2
(x,y)=(0,2)
The coordinates are (2,0) and the solicited matrix entry is: 7
Right: 8
Left: 9
Up: 4
Down: 1
Upleft: 6
Upright: 5
Downleft: 3
Downright: 2