8
\$\begingroup\$

The case scenario:

A 2-D array is given:

1  3  6  10 15
2  5  9  14 19 
4  8  13 18 22
7  12 17 21 24
11 16 20 23 25

and its size N is given as 5.

The program should output it as

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 

The code I wrote for this problem:

#include <stdio.h>

void main()
{
    int N = 5;
    int pixel_array[5][5] = {
        {1, 3, 6, 10, 15}, {2, 5, 9, 14, 19}, {4, 8, 13, 18, 22}, {7, 12, 17, 21, 24}, {11, 16, 20, 23, 25}

    };

    for (int row = 0; row < N; row++)
    {
        if (row < N - 1)
        {
            for (int temp_row = row, col = 0; temp_row >= 0; temp_row--, col++)
                printf("%d ", pixel_array[temp_row][col]);
        }
        else
        {
            for (int col = 0; col < N; col++)
                for (int temp_col = col, temp_row = N - 1; temp_col < N; temp_col++, temp_row--)
                    printf("%d ", pixel_array[temp_row][temp_col]);
        }
    }
}

The above code works fine and outputs the required result.

Some specific questions:

Since there are many for loops here -

  • how can I decrease code length?
  • how can I improve the efficiency of this program?
  • Any other programming practices to be implemented?

Any advice would help.

\$\endgroup\$
  • \$\begingroup\$ Please remove the part with "ascending order". It Is irelevant And confusing because it only happens to produce ascending order in the specific case of input you provided (And some others but not for all inputs). The diagonal traversal Is the point here if i get it right... \$\endgroup\$ – slepic Jan 11 at 7:02
4
\$\begingroup\$

How can I decrease code length?

You could split your big for loop into 2 smaller ones. The first one would print all diagonals up to the main one, and the other one the remaining ones.

For instance, let's say there's a matrix like:

1 2 3
4 5 6
7 8 9

Then, your first loop would print 1 4 2 7 5 3 and the second one 8 6 9. The code would look conciser and more readable too:

for (int i = 0; i < N; i++) {
    for (int j = 0; j <= i; j++) {
        printf("%d ", pixel_array[i - j][j]);
    }
}

for (int j = 0; j < N - 1; j++) {
    for (int i = N - 1; i > j; i--) {
        printf("%d ", pixel_array[i][N - i + j]);
    }
}

How can I improve the efficiency of this program?

I don't think it's possible to make it more efficient than O(n²) as you have to go through all matrix elements to print them diagonally. So, the suggested solution is efficient enough.

Any other programming practices to be implemented

Rather than using an int type for defining a size of your array, you could use uint32_t (or uint16_t or uint64_t - it depends on your requirements). Your size cannot be negative, anyways. So, change int N = 5; to const uint32_t N = 5.

Rename your array to squareMatrix because you're actually dealing with square matrices in your app.

Also, create a method out of your algorithm block - but I'll leave it up to you.

\$\endgroup\$
  • \$\begingroup\$ size_t is the usual recommended type for object counts... \$\endgroup\$ – Toby Speight Jan 13 at 13:24
2
\$\begingroup\$

Firstly, main() must return an int:

int main(void)

We can make the array initialization easier to read with judicious use of whitespace:

static const int N = 5;
const int pixel_array[5][5] =
    {
     {1,  3,  6,  10, 15},
     {2,  5,  9,  14, 19},
     {4,  8,  13, 18, 22},
     {7,  12, 17, 21, 24},
     {11, 16, 20, 23, 25}
    };

Instead of the if/else inside the loop, notice that the else is only taken on the last iteration, and move that out:

for (int row = 0; row < N; row++)
{
    if (row < N - 1)
    {
        for (int temp_row = row, col = 0; temp_row >= 0; temp_row--, col++)
            printf("%d ", pixel_array[temp_row][col]);
    }
    else
    {
        for (int col = 0; col < N; col++)
            for (int temp_col = col, temp_row = N - 1; temp_col < N; temp_col++, temp_row--)
                printf("%d ", pixel_array[temp_row][temp_col]);
    }
}

becomes

for (int row = 0;  row < N - 1;  row++)
{
    for (int temp_row = row, col = 0; temp_row >= 0; temp_row--, col++)
        printf("%d ", pixel_array[temp_row][col]);
}

/* row == N - 1 */
for (int col = 0;  col < N;  col++)
    for (int temp_col = col, temp_row = N - 1; temp_col < N; temp_col++, temp_row--)
        printf("%d ", pixel_array[temp_row][temp_col]);

We can move the printing of the main diagonal to the first loop, so that its condition is row < N and remove it from the second loop by starting col at 1. Also observe that temp_row and temp_col can always be derived from row and column:

for (int row = 0;  row < N;  ++row) {
    for (int col = 0;  col <= row;  ++col) {
        printf("%d ", pixel_array[row-col][col]);
    }
}

for (int col = 1;  col < N;  ++col) {
    for (int row = N - 1;  row >= col;  --row) {
        printf("%d ", pixel_array[row][col+N-1-row]);
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.