Home > Mobile >  Matrix elements between two diagonals
Matrix elements between two diagonals

Time:09-28

I need to make a matrix that would print number X between two diagonals, and the rest is number Y.

Right diagonal is: 'i==j' Left diagonal is: 'i j==n-1'

The problem here is to select elements that are between them.

Picture of matrix:

matrix

Code:

#include <stdio.h>

int main() {
  int i, j, n = 5, x = 4, y = 6;
  int mat[100][100];
  for (i = 0; i < n; i  )
    for (j = 0; j < n; j  ) {
      if (i == j || i   j >= n - 1 || j < i) mat[i][j] = y;
      else mat[i][j] = x;
    }
  for (i = 0; i < n; i  ) {
    for (j = 0; j < n; j  )
      printf("%d ", mat[i][j]);
    printf("\n");
  }
  return 0;
}

OUTPUT:

6 4 4 4 6

6 6 4 6 6

6 6 6 6 6

6 6 6 6 6

6 6 6 6 6

Could you please help me to fix the remaining part of matrix? I just need to make number X between the main diagonals in the lower part of matrix.

CodePudding user response:

The upper and lower triangles can be isolated with separate tests:

#include <stdio.h>

int main() {
    int i, j, n = 5, x = 4, y = 6;
    int mat[n][n];
    for (i = 0; i < n; i  ) {
        for (j = 0; j < n; j  ) {
            if (j > i && j < n - i - 1) {
                /* upper triangle */
                mat[i][j] = x;
            } else
            if (j < i && j > n - i - 1) {
                /* lower triangle */
                mat[i][j] = x;
            } else {
                /* everywhere else */
                mat[i][j] = y;
            }
        }
    }
    for (i = 0; i < n; i  ) {
        for (j = 0; j < n; j  )
            printf("%d ", mat[i][j]);
        printf("\n");
    }
    return 0;
}

Since you set the same value in both triangles, you can combine the tests as a single expression:

#include <stdio.h>

int main() {
    int i, j, n = 5, x = 4, y = 6;
    int mat[n][n];
    for (i = 0; i < n; i  ) {
        for (j = 0; j < n; j  ) {
            if ((j > i && j < n - i - 1) || (j < i && j > n - i - 1))
                mat[i][j] = x;
            else
                mat[i][j] = y;
        }
    }
    for (i = 0; i < n; i  ) {
        for (j = 0; j < n; j  )
            printf("%d ", mat[i][j]);
        printf("\n");
    }
    return 0;
}

CodePudding user response:

You can express the diagonals in terms of i and n, like you did. Just instead, bring j to the left of the expression. I have written them out as d1 and d2:

#include <stdio.h>
#include <sys/param.h>

int main() {
  int i, j, n = 5, x = 4, y = 6;
  int mat[n][n];
  for (i = 0; i < n; i  )
    for (j = 0; j < n; j  ) {
      int d1 = i;
      int d2 = n - i - 1;
      if (j > MIN(d1, d2) && j < MAX(d1, d2)) mat[i][j] = x;
      else mat[i][j] = y;
    }
  for (i = 0; i < n; i  ) {
    for (j = 0; j < n; j  )
      printf("%d ", mat[i][j]);
    printf("\n");
  }
  return 0;
}

I have taken MIN and MAX from sys/param.h, but you might want to define those yourself, whatever suits your needs.

Note that I have also inverted the assignment of x and y to make it easier to explain from the picture: If j on line i is between d1 and d2, then make it x, otherwise make it y.

CodePudding user response:

Simply count inward from the left and right margin, appropriate to the row. When you reach the centre, reverse the direction of counting. Simple.

int main() {
    int i, j, n = 11, x = 4, y = 6;

    int cnt = 0;

    int mat[100][100];
    for (i = 0; i < n; i  ) {
        for (j = 0; j < n; j  )
            mat[i][j] = ( j>cnt && j<(n-cnt-1) ) ? x : y;
        cnt  = i < n/2 ? 1 : -1;
    }

    for (i = 0; i < n; i  ) {
        for (j = 0; j < n; j  )
            printf("%d ", mat[i][j]);
        printf("\n");
    }
    return 0;
}

Since the pattern is symmetric both horizontally and vertically, why not populate more cells at the same time:

int main() {
    int i, j, n = 11, x = 4, y = 6;

    int mat[100][100];
    for (i = 0; i < (n 1)/2; i  )
        for (j = 0; j < (n 1)/2; j  )
            mat[i    ][j    ] =
            mat[n-1-i][j    ] =
            mat[i    ][n-1-j] =
            mat[n-1-i][n-1-j] =
            ( j>i && j<(n-1-i) ) ? x : y;

    for (i = 0; i < n; i  ) {
        for (j = 0; j < n; j  )
            printf("%d ", mat[i][j]);
        printf("\n");
    }
    return 0;
}

Since the stated objective is to print the pattern, there's no need for the matrix and separate operations:

int main() {
    int cnt = 0, n = 11;

    for( int i = 0; i < n; i   ) {
        for ( int j = 0; j < n; j   )
            putchar( "64"[ j>cnt && j<(n-cnt-1) ] );
        cnt  = i < n/2 ? 1 : -1;
        puts( "" );
    }

    return 0;
}

And, a final version that "works outward from the centre" (with the proviso that the values are all small):

#include <string.h>

int main() {
    const uint8_t n = 11, x = 4, y = 6;
    uint8_t mat[n][n];

    memset( mat, y, sizeof mat );
    for( int r = 1, w = 1, c = n>>1; r < (n 1)/2; r  , w  = 2 ) {
        memset( &mat[c-r][c-r 1], x, w );
        memset( &mat[c r][c-r 1], x, w );
    }

// Alternatively as a single statement without needing braces:
//  for( int r = 1, w = 1, c = n>>1; r < (n 1)/2; r  , w  = 2 )
//      memcpy( &mat[c r][c-r 1], memset( &mat[c-r][c-r 1], x, w ), w );

    for( int i = 0; i < n; i   ) {
        for( int j = 0; j < n; j   )
            printf("%d ", mat[i][j]);
        puts( "" );
    }

    return 0;
}

So many ways to skin a cat...

  • Related