-1

I have coding problem to write concentric square matrix (biggest number is in the middle) For example user needs to write an matrix For example:

                 5 5 5 5 5 
                 5 6 6 6 5
                 5 6 7 6 5     
                 5 6 6 6 5 
                 5 5 5 5 5

My program has to output "Yes" because this is, by my program's rules, a concentric square matrix.

                 5 5 5 5 5 
                 5 6 6 6 5
                 5 6 7 8 5     
                 5 6 6 6 5 
                 5 5 5 5 5

This is not a concentric square matrix because 8 is in 4th column and 3rd row.

This is my code:

#include <stdio.h>

int main() {
    
    int mat[100][100];
    int i,j;
    int n;
    scanf("%d",&n);
    printf("Unesite matricu; ");
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            scanf("%d",&mat[i][j]);
        }
    }    
}

I don't know how to do the rest of it so if someone can help me, I would be happy :))

Comment::

I forgot to say that only odd numbers can be the dimension of the matrix (1,3,11,27). The only final output of the program has to be "YES (if the matrix is a concentric square matrix) or "NO" (if it's not). I know how to make a concentric square matrix when the user inputs a number (for example, 4) and the matrix has 2*n-1 dimensions. And through the loops, the program automatically makes the matrix (if you know what I mean). But for my matrix, the user has to input all the elements of the matrix and the program has to check if the matrix is concentric or not.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Welcome to Stack Overflow. Please read the [About] and [Ask] pages. What you've shown is a decent start. Now you need to spend some time working on how you determine if the matrix entered matches your "concentric matrix" definition. Your examples are 5x5 matrices; what does a 4x4 or 6x6 concentric matrix look like? You need to think about how you can scan around one 'shell' of your matrix, looking for mismatching characters. If the shells are all correct, then you can scan down the leading diagonal to the middle to check that the values are monotonically increasing (or consecutive). – Jonathan Leffler Jan 21 '22 at 00:31
  • 1
    The program you have posted will not produce the output you have printed. It won't produce any output other than the one printf statement that you have. Can you post the actual code you are using to print the output you have – cup Jan 21 '22 at 00:37
  • [This answer](https://stackoverflow.com/questions/70502661/fill-matrix-in-spiral-form-from-center/70503168#70503168) shows how to traverse the shells starting from the middle. – user3386109 Jan 21 '22 at 00:48
  • @cup"Unesite matricu: " means "enter the members of the matrix". I forgot to say that only odd numbers can be dimension of matrix (1,3,11,27). The only final output of programe has to be "YES (if matrix is concentric square matrix) or "NO" (if its not). I know how to make concentric square matrix when user inputs number for example: 4 and matrix has 2*n-1 dimensions. And trough the loops programe automatically makes matrix (if you know what i mean). But for my matrix user has to input all the elements of matrix and programe has to check if matrix is concentric or not. – mr fahrenheit Jan 21 '22 at 00:58
  • If you know how to make the concentric square matrix, then all you need to do is run that code, but instead of writing values into the matrix, you compare what the user put in the matrix with what your code would write into the matrix. – user3386109 Jan 21 '22 at 01:50
  • Would shells with values 1, 3, 5, 7 be OK, or must the numbers increase by one in each inner shell? What about 1, 2, 5, 9, 10 (irregular increments)? – Jonathan Leffler Jan 21 '22 at 16:36

2 Answers2

1

Would you please try the following:

#include <stdio.h>

int main() {

    int mat[100][100];
    int ii[] = {0, 1, 0, -1};           // incremental numbers of i
    int jj[] = {1, 0, -1, 0};           // incremental numbers of j

    int i, j;
    int n;
    int u, v, w;                        // variables to walk on edges
    int val;                            // value of the element
    int prev;                           // previous value in one outer edge
    int length;                         // length of the edge

    // read matrix size and values
    printf("Enter the number:\n");
    scanf("%d", &n);

    printf("Enter the matrix:\n");
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            scanf("%d", &mat[i][j]);
        }
    }

    // loop on the edges
    for (u = 0; u < n / 2; u++) {       // from outmost edge to inner
        i = u; j = u;                   // index of the north west corner
        val = mat[u][u];                // initial value to compare
        for (v = 0; v < 4; v++) {       // four sides
            length = n - u * 2 - 1;     // length of the edge
            for (w = 0; w < length; w++) {
                i += ii[v];             // one step ahead on the edge
                j += jj[v];             // same as above
                if (mat[i][j] != val || (u > 0 && mat[i][j] <= prev)) {
                                        // if u == 0, skip the comparison with prev
                    printf("No at [%d][%d] (val=%d)\n", i, j, mat[i][j]);
                    return 1;
                }
            }
        }
        prev = mat[i][j];
    }

    // finally examine the center value (if n is odd number)
    if (n % 2) {
        if (mat[u][u] <= prev) {
            printf("No at [%d][%d] (val=%d)\n", u, u, mat[u][u]);
            return 1;
        }
    }

    printf("Yes\n");
    return 0;
}

The basic concept is to generate a series of indexes of the edge such as:

[0, 1], [0, 2], [0, 3], [0, 4],
[1, 4], [2, 4], [3, 4], [4, 4],
[4, 3], [4, 2], [4, 1], [4, 0],
[3, 0], [2, 0], [1, 0], [0, 0]

by using the variables i, j and the arrays ii[], jj[].
The example above is the indexes for the outermost edge and go into the inner edge in the next iteration. Then the values of the index is compared with the other value in the same edge and the previous value in the outer edge.

[Edit]
Here is an alternative which does not use an array other than mat[100][100]:

#include <stdio.h>

int main() {

    int mat[100][100];
    int i, j;
    int ii, jj;                         // incremental values for i and j
    int n;
    int u, v, w;                        // variables to walk on edges
    int val;                            // value of the element
    int prev;                           // previous value in one outer edge
    int length;                         // length of the edge

    // read matrix size and values
    printf("Enter the number:\n");
    scanf("%d", &n);

    printf("Enter the matrix:\n");
    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            scanf("%d", &mat[i][j]);
        }
    }

    // loop on the edges
    for (u = 0; u < n / 2; u++) {       // from outmost edge to inner
        i = u; j = u;                   // index of the north west corner
        val = mat[u][u];                // initial value to compare
        for (v = 0; v < 4; v++) {       // four sides
            ii = (v & 1) * ((v & 1) - (v & 2));
                                        //  assigned to {0, 1, 0, -1} in order
            jj = ((v + 1) & 1) * (((v + 1) & 1) - ((v + 1) & 2));
                                        //  assigned to {1, 0, -1, 0} in order
            length = n - u * 2 - 1;     // length of the edge
            for (w = 0; w < length; w++) {
                i += ii;                // one step ahead on the edge
                j += jj;                // same as above
                if (mat[i][j] != val || (u > 0 && mat[i][j] <= prev)) {
                                        // if u == 0, skip the comparison with prev
                    printf("No at [%d][%d] (val=%d)\n", i, j, mat[i][j]);
                    return 1;
                }
            }
        }
        prev = mat[i][j];
    }

    // finally examine the center value (if n is odd number)
    if (n % 2) {
        if (mat[u][u] <= prev) {
            printf("No at [%d][%d] (val=%d)\n", u, u, mat[u][u]);
            return 1;
        }
    }

    printf("Yes\n");
    return 0;
}
tshiono
  • 21,248
  • 2
  • 14
  • 22
  • Thank you very much. This works. But i have one question can this be made only by using one matrix "mat[100][100]" and not using any array or other matrices? Jus using one matrix and thats it. – mr fahrenheit Jan 21 '22 at 10:30
  • Are you mentioning about `ii[]` and `jj[]`? The answer is yes, we can. Instead we need to put `if (..)` condition or other calculation to change the direction (incremental values for `i` and `j`) within the `loop on the edges`. I suppose it may be easier and more readable to use `ii[]` and `jj[]`. Is there any restrictions for you as an assignment? – tshiono Jan 21 '22 at 11:00
  • I've updated my answer with an alternative which does not use other arrays. BR. – tshiono Jan 21 '22 at 11:23
  • I observe that this produces a negative response for valid matrices where the size of the matrix is an even number. It also consciously rejects matrices where any of the entries is negative — it isn't clear from the specification whether negative values are allowed in the matrix, so this shouldn't be held against it. (The fix might be as simple as protecting the test after the loops with `if (n % 2 == 1) { …current test… }` — the test results are then the same as for all my test cases not using negative numbers.) – Jonathan Leffler Jan 21 '22 at 19:28
  • And I see that there is a comment stating that the size must be odd — which is fine though it isn't really clear why even matrices can't be analyzed too. – Jonathan Leffler Jan 21 '22 at 19:38
  • #Jonathan Leffler its ok i fixed what i neded, All good. – mr fahrenheit Jan 21 '22 at 20:35
  • @JonathanLeffler thank you for the suggestions. I was just being lazy to support negative elements and the even number sized matrix. Now I've fixed the code to support them as well. – tshiono Jan 22 '22 at 05:46
  • Looks good, @tshiono. I can't upvote a second time. – Jonathan Leffler Jan 22 '22 at 05:48
0

I created an answer using more functions than just main(). It is more verbose than what is required for your homework — it prints out the matrix it reads and diagnoses the first problem it comes across. It works with both positive and negative numbers, and with matrices with odd or even numbers of elements.

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

enum { MAT_SIZE = 100 };

static int err_error(const char *fmt, ...)
{
    va_list args;
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
    exit(EXIT_FAILURE);
}

static int err_shell(int r, int c, int a_val, int e_val)
{
    printf("Element M[%d][%d] = %d vs expected value %d\n", r, c, a_val, e_val);
    return 0;
}

static int check_shell(int shell, int n, int matrix[MAT_SIZE][MAT_SIZE])
{
    int lb = shell;
    int ub = n - shell - 1;
    int val = matrix[lb][lb];

    /* Check the horizontals */
    for (int c = lb; c <= ub; c++)
    {
        if (matrix[lb][c] != val)
            return err_shell(lb, c, matrix[lb][c], val);
        if (matrix[ub][c] != val)
            return err_shell(ub, c, matrix[ub][c], val);
    }

    /* Check the verticals */
    for (int r = lb; r <= ub; r++)
    {
        if (matrix[r][lb] != val)
            return err_shell(r, lb, matrix[r][lb], val);
        if (matrix[r][ub] != val)
            return err_shell(r, ub, matrix[r][ub], val);
    }

    return 1;
}

static int check_matrix(int n, int matrix[MAT_SIZE][MAT_SIZE])
{
    for (int i = 0; i <= n / 2; i++)
    {
        if (check_shell(i, n, matrix) == 0)
            return 0;
    }

    for (int i = 0; i < (n - 1) / 2; i++)
    {
        if (matrix[i][i] >= matrix[i+1][i+1])
        {
            printf("Shell %d has value %d but inner shell %d has value %d\n",
                   i, matrix[i][i], i+1, matrix[i+1][i+1]);
            return 0;
        }
    }
    return 1;
}

static int read_size(void)
{
    int n;
    if (scanf("%d", &n) != 1)
        err_error("failed to read an integer\n");
    if (n <= 0 || n > MAT_SIZE)
        err_error("matrix size %d is not in the range 1..%d\n", n, MAT_SIZE);
    return n;
}

static void read_matrix(int n, int matrix[n][n])
{
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (scanf("%d", &matrix[i][j]) != 1)
                err_error("failed to read M[%d][%d]\n", i, j);
        }
    }
}

static int max_field_width(int n, int matrix[MAT_SIZE][MAT_SIZE])
{
    int min_val = matrix[0][0];
    int max_val = matrix[0][0];
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (matrix[i][j] < min_val)
                min_val = matrix[i][j];
            if (matrix[i][j] > max_val)
                max_val = matrix[i][j];
        }
    }
    int fld_width = snprintf(0, 0, "%d", max_val);
    if (min_val < 0)
    {
        int min_width = snprintf(0, 0, "%d", min_val);
        if (min_width > fld_width)
            fld_width = min_width;
    }
    return fld_width;
}

static void print_matrix(const char *tag, int n, int matrix[MAT_SIZE][MAT_SIZE])
{
    printf("%s (%d):\n", tag, n);
    int w = max_field_width(n, matrix) + 1;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            printf("%*d", w, matrix[i][j]);
        }
        putchar('\n');
    }
}

int main(void)
{
    int matrix[MAT_SIZE][MAT_SIZE];
    int n = read_size();
    read_matrix(n, matrix);
    print_matrix("Input", n, matrix);
    if (check_matrix(n, matrix))
        printf("YES: Matrix is a valid concentric matrix\n");
    else
        printf("NO: Matrix is not a valid concentric matrix\n");
    return 0;
}

One detail is that this code can be made to use a VLA (variable-length array) by simply replacing MAT_SIZE by n in each function definition and modifying main() to read:

static int check_shell(int shell, int n, int matrix[n][n]) { … }
static int check_matrix(int n, int matrix[n][n]) { … }
static void read_matrix(int n, int matrix[n][n]) { … }
static int max_field_width(int n, int matrix[n][n]) { … }
static void print_matrix(const char *tag, int n, int matrix[n][n]) { … }

int main(void)
{
    int n = read_size();
    int matrix[n][n];
    read_matrix(n, matrix);
    print_matrix("Input", n, matrix);
    if (check_matrix(n, matrix))
        printf("YES: Matrix is a valid concentric matrix\n");
    else
        printf("NO: Matrix is not a valid concentric matrix\n");
    return 0;
}

This reads the matrix size before allocating the matrix, instead of allocating a fixed size matrix first. The read_size() function enables this change — that input must be done separately from the main matrix scanning code.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278