Home > Mobile >  Comparing the elements of a matrix to each other "column-wise" in C
Comparing the elements of a matrix to each other "column-wise" in C

Time:07-17

Forgive me if the title is misleading/inappropriate.

What I want to accomplish: Let's say I have an n-by-m matrix. I wish to compare each element with the remaining elements in the same column, count the number of times the test element exceeds or equals the other elements, and store that value (no. of times) each time for further use. First, I tried to code a similar program (in C) for a 2-by-2 matrix. The code is given below:

#include<stdio.h>
int main()
{
    int M[2][2]={
    {4,6},
    {9,2},
    };
    int i,j,row,col;
    int arr[2][2]={0};
    int t;
    for(i=0;i<2;  i)
    {
        for(j=0;j<2;  j)
        {
            t=M[i][j];
            for(col=0;col<2;  col)
            {
                for(row=0;row<2;  row)
                {
                    if(row==i && col==j)
                        continue;
                    else if(t>=M[row][col])
                        arr[i][j] =1;
                }
            }
        }
    }
    printf("The Matrix:\n");
    for(i=0;i<2;  i){
        for(j=0;j<2;  j)
            printf("%d  ",arr[i][j]);
        printf("\n");
    }
    return 0;
}  

The output is:

[0  0;0  0]

But, the desired output should be:

[0  1;1  0]

So, I have made some blunder. I think the "no. of times" values aren't getting updated properly in the 2D array arr[2][2]. However, I am not able to think of a way to overcome this thing at present. Please suggest how to resolve the issue.

CodePudding user response:

As Jonathan Leffler mentioned in a comment above, 4 nested loops are too much. You can achieve what you want using 3 nested loops:

size_t count_ge(const size_t nrows, const size_t ncols, int in[nrows][ncols], int out[nrows][ncols])
{
    for (size_t j = 0; j < ncols;   j) {
        for (size_t i = 0; i < nrows;   i) {
            for (size_t k = 0; k < nrows;   k) {
                if (k == i)
                    continue;
                
                if (in[i][j] >= in[j][k])
                    out[i][j]  = 1;
            }
        }
    }
}

Applying this on the same example you provided:

int main(void)
{
    int array[2][2] = {{4, 6}, {9, 2}};
    int counts[2][2] = {{0}};
    
    count_ge(2, 2, array, counts);
    print_array_2d(2, 2, counts);
}

Output:

0 1
1 0

The other function:

void print_array_2d(const size_t nrows, const size_t ncols, int array[nrows][ncols])
{
    for (size_t i = 0; i < nrows;   i)
        print_array_1d(ncols, array[i]);
}

which calls:

void print_array_1d(const size_t size, int array[size])
{
    for (size_t i = 0; i < size;   i)
        printf("%d ", array[i]);
    printf("\n");
}

CodePudding user response:

As I noted in comments:

I would expect to use three nested loops, not four. Are you sure you need four levels?

With a program using 3 nested loops, I would expect the outermost loop to select each column in turn, the middle loop would cycle through the rows in the column, and the innermost loop would scan over the remaining elements in the column, counting the number of times the current element (test element, identified by the loop indices of the outer two loops) is not smaller than the remaining elements identified by the innermost loop. I don't see what the fourth loop could be doing.

Your 2x2 test case is nice and small, but IMO it is too small for comfort. There's no need to go dramatically big, but bigger than 2x2 would be good (3x3, 3x4, 4x3 would be sufficient).

As John Bollinger noted in a comment, your code actually produces a different result from the one you claim:

1  2
3  0

The code below implements what I outlined in the comment about how 3 loops would work. The code does not rely on the result matrix being initialized. Note the use of functions to print matrices and to do the calculation. This allows for easier testing of multiple sets of test data. Indeed, I have a variant of the code shown that wraps the print-compute-print sequence into a function, so that the main() program simply defines some matrices and calls that function to do the work.

The non-standard header matmaxfldwid.h is available in my SOQ (Stack Overflow Questions) repository on GitHub in the src/libsoq sub-directory. It provides a macro max_field_width that invokes inline functions to calculate the necessary width for printing all the elements of a matrix in a uniform width (so it's a "header-only" library function). You can ignore how it works; suffice to say, it does.

My test matrices are generated by a (complex) shell script that is not currently available in my SOQ repository.

#include <stdio.h>
#include "matmaxfldwid.h"

static void dump_matrix(const char *tag, size_t rows, size_t cols, int matrix[rows][cols])
{
    printf("%s (%zux%zu):\n", tag, rows, cols);
    int fldwid = max_field_width(rows, cols, matrix);

    for (size_t r = 0; r < rows; r  )
    {
        const char *pad = "";
        for (size_t c = 0; c < cols; c  )
        {
            printf("%s%*d", pad, fldwid, matrix[r][c]);
            pad = " ";
        }
        putchar('\n');
    }
}

static void count_matrix(size_t rows, size_t cols, int matrix[rows][cols], int result[rows][cols])
{
    for (size_t c = 0; c < cols; c  )
    {
        for (size_t r = 0; r < rows; r  )
        {
            int value = matrix[r][c];
            int count = 0;
            for (size_t i = r   1; i < rows; i  )
            {
                if (value >= matrix[i][c])
                    count  ;
            }
            result[r][c] = count;
        }
    }
}

int main(void)
{
    /* Created by: gen_matrix -n N -L -99 -H  99 -r 5 -c 6 -E -w 3 -i */
    /* Random seed: 0x8E280D99 */
    int N[5][6] =
    {
        {  79, -40,  52,  26, -35,  86, },
        { -68,  13,  21, -34,  -9,  10, },
        {   7,  72,  68,  44,  45,  -3, },
        {  25,  78,  86,  81,  51, -33, },
        { -38, -89,  42,  61, -24,  69, },
    };
    enum { N_ROWS = 5, N_COLS = 6 };
    int result1[N_ROWS][N_COLS];

    dump_matrix("N", N_ROWS, N_COLS, N);
    count_matrix(N_ROWS, N_COLS, N, result1);
    dump_matrix("Result", N_ROWS, N_COLS, result1);
    putchar('\n');

    /* Created by: gen_matrix -n matrix -L -9 -H  9 -r 8 -c 6 -E -w 2 -i */
    /* Random seed: 0x00B6E0F7 */
    int matrix[8][6] =
    {
        { -3, -5,  5, -4,  7,  9, },
        {  9,  9, -9, -2,  4, -3, },
        {  2,  5, -8,  9, -7, -5, },
        {  5, -9, -5,  8,  2,  2, },
        {  5,  2, -5, -9,  4, -5, },
        {  1, -5, -3, -2,  4,  5, },
        {  8,  5,  3, -2,  1,  9, },
        {  4,  3,  2,  2,  9, -1, },
    };
    enum { MATRIX_ROWS = 8, MATRIX_COLS = 6 };
    int result3[MATRIX_ROWS][MATRIX_COLS];

    dump_matrix("Matrix", MATRIX_ROWS, MATRIX_COLS, matrix);
    count_matrix(MATRIX_ROWS, MATRIX_COLS, matrix, result3);
    dump_matrix("Result", MATRIX_ROWS, MATRIX_COLS, result3);
    putchar('\n');

    int M[2][2] =
    {
        {4, 6},
        {9, 2},
    };
    int result2[2][2];

    dump_matrix("M", 2, 2, M);
    count_matrix(2, 2, M, result2);
    dump_matrix("Result", 2, 2, result2);
    putchar('\n');

    printf("Original code:\n");
    dump_matrix("M", 2, 2, M);

    int i, j, row, col;
    int arr[2][2] = {0};
    int t;
    for (i = 0; i < 2;   i)
    {
        for (j = 0; j < 2;   j)
        {
            t = M[i][j];
            for (col = 0; col < 2;   col)
            {
                for (row = 0; row < 2;   row)
                {
                    if (row == i && col == j)
                        continue;
                    else if (t >= M[row][col])
                        arr[i][j]  = 1;
                }
            }
        }
    }

    printf("The Matrix:\n");
    for (i = 0; i < 2;   i)
    {
        for (j = 0; j < 2;   j)
            printf("%d  ", arr[i][j]);
        printf("\n");
    }

    return 0;
}

When run, it produces the output:

N (5x6):
 79 -40  52  26 -35  86
-68  13  21 -34  -9  10
  7  72  68  44  45  -3
 25  78  86  81  51 -33
-38 -89  42  61 -24  69
Result (5x6):
4 1 2 1 0 4
0 1 0 0 1 2
1 1 1 0 1 1
1 1 1 1 1 0
0 0 0 0 0 0

Matrix (8x6):
-3 -5  5 -4  7  9
 9  9 -9 -2  4 -3
 2  5 -8  9 -7 -5
 5 -9 -5  8  2  2
 5  2 -5 -9  4 -5
 1 -5 -3 -2  4  5
 8  5  3 -2  1  9
 4  3  2  2  9 -1
Result (8x6):
0 2 7 1 6 7
6 6 0 3 5 2
1 5 0 5 0 1
3 0 1 4 1 2
2 1 0 0 2 0
0 0 0 1 1 1
1 1 1 0 0 1
0 0 0 0 0 0

M (2x2):
4 6
9 2
Result (2x2):
0 1
0 0

Original code:
M (2x2):
4 6
9 2
The Matrix:
1  2  
3  0  
  • Related