Accessing data in neighbor cells - c

I have a matrix M of size m x n which is saved as a one dimensional array N of length m * n. Every cell of this array contains some integer variables which are the ID of data points. The amount of integer variables in every cell changes over time.
N[0] = {1,4,5,7}
N[1] = {2,9,3,1,7,4}
N[2] = {7,1,3,9,8}
N[3] = {6,4,2}
...
I access these elements by using an index function which returns
idx = x + y * n
Given some index idx I want to use all integer variables of the neighbor cells and the central cell with index idx to access an array of data points D of size s. Size s can be very large.
To make my point clear: Instead of such a loop over all data points
for(int i=0; i<s; i++)
// Do something with D[i]
I want something like (but more compact)
// Access central cell
idx = x + y*n;
num_Elements = Number_of_Elements_Cell(x,y);
for(int i=0; i<num_Elements; i++)
// Do something with D[N[idx][i]]
// Access right cell
idx = (x+1) + y*n;
num_Elements = Number_of_Elements_Cell(x+1,y);
for(int i=0; i<num_Elements; i++)
// Do something with D[N[idx][i]]
// Access left cell
idx = (x-1) + y*n;
num_Elements = Number_of_Elements_Cell(x-1,y);
for(int i=0; i<num_Elements; i++)
// Do something with D[N[idx][i]]
and so on. For all cells I have to do that 9 times.
My question: Is there a better way to do that given the structure N?

I'm not sure i understand your question well ....
but you could try :
for (int i=-1 ; i <= 1 ; i++){
for (int j = -1 ; j <=1 ; j++){
idx = (x+i) + (y+j)*n;
// Check if idx is not out of bounds
num_Elements = Number_of_Elements_Cell(x+i,y+j);
for(int k=0; k<num_Elements; k++)
// Do something with D[N[idx][k]]
}
}
Note that your index could very well be out-of-bounds which such a method, so you'll have to implement a test to prevent that.
That's the way to simply iterate on a cell and its 8 neighbors using a double for loop.
If it's not what you expect, let me know, i'll edit/delete.

I'm not sure but maybe you're looking for something like this:
var distinctDataPoints = new List<int>();
for(int z = x - 1, z <= x + 1, z++)
{
if(z < 0 || z > m)
continue;
for(int t = y-1, t <= y + 1, t++)
{
if(t < 0 || t > n)
continue;
idx = z + t * n;
for(int i = 0; i < num_Elements; i++)
{
if(!distinctDataPoints.Contains(N[idx][i])
distinctDataPoints.Add(N[idx][i])
}
}
}
for(int dpIdx = 0; dpIdx < distinctDataPoints.Count; dpIdx++)
{
//Do something with D[dpIdx]
}

Related

Neighbours algorithm

Hi a have a code like these:
for (int row = 0; row < a.length; row++) {
for (int col = 0; col < a[row].length; col++) {
// Do something with a[row][col];
}
}
But i want to make an operation in a grid (8-neighbours) for every a[row][col] , however when im at the corners i will have problems (i don't know how to check if im in a corner), i was thinking in code a lot of if - conditionals, but i dont know the effective way to do this..
If there is a perse method for do this types of traversal neighbours arrays i would very greatful if you could give me a link, I've spent all day looking for information and I can't find anything.
You can use these arrays which represent the changes in the indexes when you look at the neighbors from a given position:
int dx[] = {-1,0,1,1,1,0,-1,-1};
int dy[] = {-1,-1,-1,0,1,1,1,0};
At position (row, col), dx[i] represents a change in row and dy[i] represents a change in col. You can use each position in the array to look at the neighbors.
Make a helper function that checks if a position is safe:
boolean isValidPosition(int x, int y) {
return 0 <= x && x < a.length && 0 <= y && y < a[x].length;
}
Then iterate over all 8 positions and you will have access to the neighbors via a[row + dx[i]][col + dy[i]].
for (int row = 0; row < a.length; row++) {
for (int col = 0; col < a[row].length; col++) {
for (int i = 0; i < 8; i++) {
if (isValidPosition(row + dx[i], col + dy[i])) {
// Do something with a[row + dx[i]][col + dy[i]];
}
}
}
}

C - Nested loops and stack?

I am trying to find the location of a target inside of a 1-D array that acts like a table with rows and cols. I could do it using divide and mod, but I am stuck on finding it using nested loops. specifically, I can't seem to assign values inside the nested loop.
here is my code:
#include <stdio.h>
int main()
{
int arr[9] = // act as a 3 X 3 table
{ 2, 34, 6,
7, 45, 45,
35,65, 2
};
int target = 7;// r = 1; c = 0
int r = 0; // row of the target
int c = 0; // col of the target
int rows = 3;
int cols = 3;
for (int i = 0; i < rows; i++){
for (int j = 0; j + i * cols < cols + i * cols; i++ ){
if (arr[j] == target){
c = j; // columns of the target
r = i; // rows of the target
}
}
}
printf ("%d, %d",c, r);
return 0;
}
The code outputs: 0,0.
The problem isn't with the assignment, it's with the wrong loop and if condition.
The outer loop should loop over the i rows
The inner loop should loop over the j columns
within both loops, the cell to evaluate is i * cols + j
Put it all together and you'll get:
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++ ) {
if (arr[i * cols + j] == target) {
c = j; // columns of the target
r = i; // rows of the target
}
}
}
Since arr is 1D array and inside for loop, for any i value j will reach upto max 3 only so its not checking after arr[3]
To avoid this problem take int pointer and points to arr and do the operation as below
int *p = arr;
for (i = 0; i < rows; i++){
for ( j = 0; j < cols ; j++ ){
if (p[j] == target){
c = j; // columns of the target
r = i; // rows of the target
}
}
p = p + j;/*make p to points to next row */
}
A better solution would use only one loop:
for (int i = 0; i < rows * cols; i++){
if (arr[i] == target){
r = i / 3;
c = i % r;
}
}

Duplicates within 2 arrays

So what i'm doing is populating 2 arrays x_cord and y_cord with a maximum amount of values in each. In this case both arrays can hold a maximum amount of unique elements of 5 and each element must be between 0 and 2. Afterwards once the arrays are completely randomized I am writing the values into a file
It would look something like this:
0 0
1 2
2 1
2 2
0 1
I don't want any of the rows to be duplicates of no another, however I am running into trouble where I am creating duplicates of one another, any help would be appreciated.
Code:
for (j=0; j < num_pt; j++){
(x_cord[j] = rand()%max_x+1);
(y_cord[j] = rand()%max_y);
for(m=j+1; m < num_pt; m++){
if ((x_cord[j]==x_cord[m]) && (y_cord[j]==y_cord[m])){
x_cord[j] = rand()%max_x+1;
}
}
}
for (j=0; j < num_pt;j++){
fprintf(fp, "%d\t%d\n", x_cord[j], y_cord[j]);
}
Rather than repeatedly generating a pair until you find a unique pair, generate all pairs, then shuffle the pairs.
int max_y = 2;
int max_x = 2;
size_t num_eles = (max_x+1)*(max_y+1);
size_t desired_num_eles = 6;
if (desired_num_eles > num_eles)
desired_num_eles = num_eles;
int* y_cord = malloc(sizeof(int) * num_eles);
int* x_cord = malloc(sizeof(int) * num_eles);
for (int y = max_y; y--; ) {
for (int x = max_x; x--; ) {
size_t i = y * max_x + x;
y_cord[i] = y;
x_cord[i] = x;
}
}
for (size_t i = 0; i<desired_num_eles; ++i) {
size_t j = rand() % (num_eles - i) + i;
// Swap i and j
y_cord[i] ^= y_cord[j]; y_cord[j] ^= y_cord[i]; y_cord[i] ^= y_cord[j];
x_cord[i] ^= x_cord[j]; x_cord[j] ^= x_cord[i]; x_cord[i] ^= x_cord[j];
}
num_eles = desired_num_eles;
y_cord = realloc(sizeof(int) * num_eles);
x_cord = realloc(sizeof(int) * num_eles);

Delete matched pairs in an Array

I'm attempting to write a game of Go Fish where points are given for matched pairs of cards. However, I can't seem to find a way to remove the matched pairs from the hand.
I have implemented a little loop to remove single cards used in other aspects of the game, as shown here:
for ( i = position - 1 ; i < user_size - 1 ; i++)
{
user_hand[i] = user_hand[i+1];
user_count[i]--;
user_size--;
}
Where the user_size is the number of cards in the user's hand, and the user_count is how many of each of the 13 card values the user holds. I can't find a way to remove pairs of the same valued cards however.
For example if the user_hand was: 2 2 4 5 6 6 6 6 1 2
I would like to remove all but one of the 2's (one pair) and all four of the 6's (two pairs). Leaving the user_hand as: 4 5 1 2. But for the life of me I can't think of a way to do this. Any help would be greatly appreciated!
In case reordering cards in users hand is not a problem, you could:
int *hand;
int handSize;
...
sort(hand, handSize); // 1. sort
int *newHand = malloc(sizeof(int) * handSize);
int i, newHandSize = 0;
for (i = 1; i < handSize; ++i) {
if (hand[i - 1] == hand[i]) {
hand[i] = -1; // 2. "flag" last value of a pair
continue;
}
newHand[newHandSize] = hand[i - 1]; // 3. copy last examined card to new hand
newHandSize++;
}
if (hand[handSize - 1] != -1) { // 4. copy last element if needed
newHand[newHandSize] = hand[handSize - 1];
newHandSize++;
}
int* handToFree = hand;
hand = newHand; // 5. replace users hand with new hand
free(handToFree); // 6. clean up
but I don't think it can go under O( n*log(n) + n )
Normally you would use 1 array for the cards and one variable to hold the number of cards.
Then you can iterate with a nested loop like this:
for (int i = 0; i < user_size; i++){
for (int j = i+1; j < user_size; j++){
if(user_hand[i] == user_hand[j]){
/* remove card at index i */
for(int z = i; z < user_size - 1; z++) user_hand[z] = user_hand[z + 1];
user_size--;
/* remove card at index j */
for(int z = j; z < user_size - 1; z++) user_hand[z] = user_hand[z + 1];
user_size--;
}
}
}
But in your example, you also got user_count[]. If I understood you right (otherwise please correct me) user_count[] holds how many cards of a specific value the user has on his hand.
So in your example with: 2 2 4 5 6 6 6 6 1 2
user_count[0] = 0
user_count[1] = 1
user_count[2] = 3
user_count[3] = 0
user_count[4] = 1
user_count[5] = 1
user_count[6] = 4
If that's what user_count[] is for, then you could simply do:
for (int i = 0; i < user_size; i++){
for (int j = i+1; j < user_size; j++){
if(user_hand[i] == user_hand[j]){
int cardNumber = user_hand[i];
/* remove card at index i */
for(int z = i; z < user_size - 1; z++) user_hand[z] = user_hand[z + 1];
user_size--;
/* remove card at index j */
for(int z = j; z < user_size - 1; z++) user_hand[z] = user_hand[z + 1];
user_size--;
/* decrement user_count by 2 */
user_count[cardNumber] = user_count[cardNumber] - 2;
}
}
}
void removePairs(int * hand, int size)
{
for(int i = 0; i < size; i++)
{
for(int j = i+1; j < size; j++)
{
if((hand[i] == hand[j]) && hand[i] != -1)
{
hand[i] = -1; // set card "ready to remove"
hand[j] = -1;
break;
}
}
}
for(int k = 0; k < size; k++)
{
if(hand[k] != -1)
{
printf("%d ", hand[k]); // you can store remaining cards here
}
}
}
Start by looping through your user_count array, and keep calling remove_card twice as long as user_count[rank] >= 2:
for(int rank = 1; rank <= 13; rank++)
while(user_count[rank] >= 2) {
remove_card(user_hand, user_count, &user_size, rank);
remove_card(user_hand, user_count, &user_size, rank);
}
For remove_card, just find the first matching card, and call your existing routine:
void remove_card(int *user_hand, int *user_count, int *user_size, int rank) {
for(int pos = 0; pos < *user_size; pos++)
if(user_hand[pos] == rank)
remove_card_at(user_hand, user_count, user_size, pos+1);
}
remove_card_at is the routine you provided in your original post to remove a card at a particular position. Note you'll have to turn user_size into a pointer and dereference it in order to modify the variable in the calling function.
Also, you should really look into using a structure or class to hold the user's hand, depending on if you're using C or C++.

What is the best way to loop through a 2D sub-array of a 2D array?

If I have a 2D array, it is trivial to loop through the entire array, a row or a column by using for loops. However, occasionally, I need to traverse an arbitrary 2D sub-array.
A great example would be sudoku in which I might store an entire grid in a 2D array but then need to analyse each individual block of 9 squares. Currently, I would do something like the following:
for(i = 0; i < 9; i += 3) {
for(j = 0; j < 9; j += 3) {
for(k = 0; k < 3; k++) {
for(m = 0; m < 3; m++) {
block[m][k] == grid[j + m][i + k];
}
}
//At this point in each iteration of i/j we will have a 2D array in block
//which we can then iterate over using more for loops.
}
}
Is there a better way to iterate over arbitrary sub-arrays especially when they occur in a regular pattern such as above?
The performance on this loop structure will be horrendous. Consider the inner most loop:
for(m = 0; m < 3; m++) {
block[m][k] == grid[j + m][i + k];
}
C is "row-major" ordered, which means that accessing block will cause a cache miss on each iteration! That's because the memory is not accessed contiguously.
There's a similar issue for grid. Your nested loop order is to fix i before varying j, yet you are accessing grid on j as the row. This again is not contiguous and will cache miss on every iteration.
So a rule of thumb for when dealing with nested loops and multidimensional arrays is to place the loop indices and array indices in the same order. For your code, that's
for(j = 0; j < 9; j += 3) {
for(m = 0; m < 3; m++) {
for(i = 0; i < 9; i += 3) {
for(k = 0; k < 3; k++) {
block[m][k] == grid[j + m][i + k];
}
}
// make sure you access everything so that order doesn't change
// your program's semantics
}
}
Well in the case of sudoku couldn't you just store 9 3x3 arrays. Then you don't need to bother with sub arrays... If you start moving to much larger grids than sudoku you would improve cache performance this way as well.
Ignoring that, your code above works fine.
Imagine you have a 2D array a[n][m]. In order to loop a subarray q x r whose upper right corner is at position x,y use:
for(int i = x; i < n && i < x + q; ++i)
for(int j = y; j < m && j < y + r; ++j)
{
///
}
For your sudoku example, you could do this
for(int i = 0; i<3; ++i)
for(int j = 0; j < 3; ++j)
for(int locali = 0; locali < 3; ++locali)
for(int localj = 0; localkj <3; ++localj)
//the locali,localj element of the bigger i,j 3X3 square is
a[3*i + locali][3*j+localj]

Resources