user963395
user963395

Reputation:

C scanning array diagonally

I have a project in C and I have to scan an array[10][15] diagonally as in the picture below.

enter image description here

I would like to help me to find how to scan the array this way... Thank you very much.

P.S sorry for my english(I'm Greek)

Upvotes: 0

Views: 3731

Answers (7)

Kerrek SB
Kerrek SB

Reputation: 477040

Notice that along each diagonal, the difference* i - j is constant. So you have a nested double loop, where the outer one goes over the difference:

  • First round: Difference -14, arr[0][14]

  • Second round: Difference -13, arr[0][13], arr[1][14]

  • ...

  • last round: Difference +9, arr[9][0].

In code:

for (int d = -14; d < 10; ++d)
{
    for (int i = 0; i < d + 15 && i < 10; ++i)
    {
      if (i < d) continue;

      // access arr[i][i - d];
      printf("[%d, %d]\n", i, i - d);
    }
}

Note the appearance of the numbers 10 and 15 in the code; the picture is readily generalized to arbitrary array bounds.

*) Or, as @Alexey points out, the sum i + j is constant, depending on where the origin is in your picture; in that case, modify the loop as follows:

for (int d = 0; d <= 9 + 14; ++d)
{
    for (int i = 0; i <= d && i < 10; ++i)
    {
        if (i + 15 <= d) continue;
        // use arr[i][d - i];
    }
}

Upvotes: 7

BlackBear
BlackBear

Reputation: 22979

int i, j;

// left arrows
for(i = 0; i < rows; i++)
    for(j = 0; j <= i && j < columns; j++)
        doSomethingWithCell(grid[i][j]);

// bottom arrows
for(int i = 0; i < columns; i++)
    for(int j = rows - 1; j >= 0; j--)
        doSomethingWithCell(grid[j][i]);

Upvotes: 1

Victor Sorokin
Victor Sorokin

Reputation: 11996

Here's my 2 bits:

void scan_array(int* data, int height, int width, void (*handler)(int)) {
    int startY = 0;
    for (; startY < height; startY ++) {
    int ypos = startY;
    int xpos = 0;
    while (ypos >= 0 && xpos < width) {
        handler(*(data + ypos * width + xpos));
        ypos--;
        xpos++;
    }
    }

    int startX = 1;
    for (; startX < width; startX ++) {
    int xpos = startX;
    int ypos = height - 1;
    while (ypos >= 0 && xpos < width) {
        handler(*(data + ypos * width + xpos));
        ypos--;
        xpos++;
    }
    }
}

void print_elem(int elem) {
    printf("%d ", elem);
}

int main(void) {
    int data[2][3] = { {1, 2, 3}, {10, 20, 30} };
    scan_array(&data[0][0], 2, 3, print_elem);
    printf("\n========\n");

    int data2[3][2] = { {1, 2},  {10, 20}, {100, 200} };
    scan_array(&data2[0][0], 3, 2, print_elem);
    printf("\n========\n");

    int square[2][2] = { {1, 2},  {10, 20}};
    scan_array(&square[0][0], 2, 2, print_elem);
    printf("\n========\n");
}

Upvotes: 1

fbafelipe
fbafelipe

Reputation: 4952

I believe you are looking for something like this:

#include <stdio.h>

int main(int argc, char *argv[]) {
    const int ROWS = 10;
    const int COLS = 15;

    int array[ROWS][COLS];

    int i, j;

    // left arrows
    for (i = 0; i < ROWS; ++i) {
        for (j = 0; j <= i && j < COLS; ++j) {
            scanf("%d", &array[i - j][j]);
        }
    }

    // bottom arrows
    for (j = 1; j < COLS; ++j) {
        for (i = 0; i < ROWS && j + i < COLS; ++i) {
            scanf("%d", &array[ROWS - i - 1][j + i]);
        }
    }

    // dump to a file, just for testing
    FILE *fp = fopen("test.txt", "w");

    for (i = 0; i < ROWS; ++i) {
        for (j = 0; j < COLS; ++j) {
            fprintf(fp, "%d ", array[i][j]);
        }
        fputc('\n', fp);
    }

    fclose(fp);

    return 0;
}

Upvotes: 0

JimR
JimR

Reputation: 16123

I am assuming I understand your question, which I read as: I want to draw a diagonal line through an array and visit each cell that the line crosses.

Use the Bresenham Algorithm to find out which cells to visit in your array and then return an array composed of the cells that Bresenham found for you. If you read the wikipedia article I linked, you'll see functions called plot and setPixel. The input to those functions are the cells you should be reading from.

Upvotes: 0

Pablo Maurin
Pablo Maurin

Reputation: 1490

You can scan every 14 elements instead of 15. This way you get the diagonal.

Upvotes: 0

RussS
RussS

Reputation: 16576

I'm going to assume you are labeling it with the upper left most cell as 0,0 and the lower right most cell as 10,15. And doSomething is whatever you are doing in this scanning.

//First all the ones starting in col=0
for (rowStart=0; rowStart<numRows ; rowStart++){
    colStart=0; //Start on the left boundary
    rowOffset=colOffset=0;
    while (rowStart+rowOffset > 0 && colStart+colOffset<numCols){
      doSomething(array[rowStart+rowOffset][colStart+colOffset]);
      colOffset++; rowOffset--; // Move one space to the right and one space up
    }
//Second all the diagonals starting in the maxRow
for (colStart=0; colStart<numCols ; numCol++){
    rowStart=numRows-1; //Start at the bottom
    rowOffset=colOffset=0;
    while (rowStart+rowOffset > 0 && colStart+colOffset<numCols){
      doSomething(array[rowStart+rowOffset][colStart+colOffset]);
      colOffset++; rowOffset--; // Move one space to the right and one space up
    }    

}

Upvotes: 0

Related Questions