1

My assignment is to find two identical columns and show each of their elements in a 2D array. After that I have to sort one of the identical column in ascending order and the other in descending order. I have written the code for finding the identical columns, however I am having a lot of trouble displaying the individual elements of the columns after they are found. I would prefer to display the elements inside the show_columns() function in column form just like in declaration().

Looking for any tips

#include <stdio.h>
#include <stdbool.h>

void declaration(int a[100][100], int n) {
    int i, j;

    for (i = 0; i < n; i++) {
        for (j = 0; j < n; j++) {
            printf("a[%i][%i]=", i, j);
            scanf("%i", &a[i][j]);
        }
    }

    printf("\nThe matrix is : \n");
    for (i = 0; i < n; i++) {
        printf("\n");
        for (j = 0; j < n; j++) {
            printf("%d\t", a[i][j]);
       }
    }
    printf("\n\n");
}

bool columns(int rows, int cols, int i, int j, int a[rows][cols]) {
    for (int k = 0; k < rows; k++) {
        if (a[k][i] != a[k][j]) {
            return false;
        }
    }
    return true;
}

void show_columns(int rows, int cols, int a[rows][cols]) {
    for (int i = 0; i < cols; i++) {
        for (int j = i + 1; j < cols; j++) {
            if (columns(rows, cols, i, j, a)) {
                printf("\nThe columns %i si %i are identical\n", i, j);
            }
        }
    }
}

int main() {
    int a[100][100], n;
    int k;

    printf("Enter n:");
    scanf("%i", &n);

    int rows = n, cols = n;

    declaration(a, n);

    show_columns(rows, cols, a);

    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
IonC
  • 21
  • 3
  • 2
    I think you've got a bug. In `declaration`, you have `int a[100][100]`. But, in `show_columns` you have `int a[rows][cols]`. Unless `rows` _and_ `cols` are _both_ 100, then the indexing will not be the same. If `cols` is (e.g. 20), it breaks. To see this, in both functions, do: `printf("%zu\n",&a[1][0] - &a[0][0]);` They should/must be the same. – Craig Estey Feb 02 '21 at 21:36
  • How about moving the code that does the printing to a seperate function? Then you can call the new function from `declaration` and from `show_columns`. – Zois Tasoulas Feb 02 '21 at 21:37
  • @CraigEstey I have looked into that and fixed it, but it still does not help me find a way to find and post the individual elements out of the identical columns. I have also created a separate function for showing the elements from declaration() but it still would not work with the show_columns() function. – IonC Feb 03 '21 at 08:36
  • It would also be helpful if anyone could help me find identical columns in an array without resorting to a bool function – IonC Feb 03 '21 at 10:21

1 Answers1

1

It would also be helpful if anyone could help me find identical columns in an array without resorting to a bool function

Well, it might be possible, but a bool function is at the core (e.g. a function that returns true if two different columns match).

But, to find all matches, another function is required. It must iterate over unique column pairings and call the match function to see if the two columns match.

It helps to define an "iterator" struct that keeps track of the search indexes and maximum geometry.


Here's a [completely] refactored version. It has a diagnostic test that generates a random matrix with random identical columns. It iterates over all column pairs and prints the unique matching column numbers.

Note that it does not sort any columns. This is left as an exercise for the reader.

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

unsigned int opt_R;
int opt_M;

typedef struct {
    int maxrow;                         // maximum number of rows
    int maxcol;                         // maximum number of columns
    int lcol;                           // starting left column
    int rcol;                           // starting right column
    int match;                          // 1=match
} search_t;

#define MAXROW      100
#define MAXCOL      100

int arrbig[MAXROW][MAXCOL];

// search_init -- initialize for full matrix search
void
search_init(search_t *srch,int maxrow,int maxcol)
{

    srch->maxrow = maxrow;
    srch->maxcol = maxcol;

    srch->lcol = 0;
    srch->rcol = 1;
}

// search_match -- decide if two given columns match
// RETURNS: 1=match
int
search_match(int lcol,int rcol,int maxrow,int arr[MAXROW][MAXCOL])
{
    int match = 0;

    for (int irow = 0;  irow < maxrow;  ++irow) {
        match = (arr[irow][lcol] == arr[irow][rcol]);
        if (! match)
            break;
    }

    return match;
}

// search_next -- advance to next search starting point
// RETURNS: 1=more to do
int
search_next(search_t *srch)
{
    int maxcol = srch->maxcol;

    srch->rcol += 1;

    if (srch->rcol >= maxcol) {
        srch->lcol += 1;
        srch->rcol = srch->lcol + 1;
    }

    return (srch->lcol < (maxcol - 1));
}

// search_find -- find next column pair that matches
int
search_find(search_t *srch,int arr[MAXROW][MAXCOL])
{
    int lcol = srch->lcol;
    int rcol = srch->rcol;
    int maxrow = srch->maxrow;
    int maxcol = srch->maxcol;
    int match = 0;

    while (lcol < (maxcol - 1)) {
        for (;  rcol < maxcol;  ++rcol) {
            match = search_match(lcol,rcol,maxrow,arr);
            if (match)
                break;
        }
        if (match)
            break;

        if (! search_next(srch))
            break;

        rcol = srch->rcol;
        lcol = srch->lcol;
    }

    srch->lcol = lcol;
    srch->rcol = rcol;
    srch->match = match;

    return match;
}

// dojoin -- ensure unique pairing
void
dojoin(const search_t *srch,int arr[MAXROW][MAXCOL])
{
    int lcol;
    int rcol;
    search_t *uniq;
    search_t uniqlist[opt_M];

    // make certain columns identical
    for (int iter = 0;  iter < opt_M;  ++iter) {
        while (1) {
            // get two different column numbers
            while (1) {
                lcol = rand() % srch->maxcol;
                rcol = rand() % srch->maxcol;
                if (lcol != rcol)
                    break;
            }

            // we want low/high
            if (lcol > rcol) {
                int tmp = lcol;
                lcol = rcol;
                rcol = tmp;
            }

            // have we set this before?
            int match = 0;
            for (int uniqidx = 0;  uniqidx < iter;  ++uniqidx) {
                uniq = &uniqlist[uniqidx];
                match = ((lcol == uniq->lcol) && (rcol == uniq->rcol));
                if (match)
                    break;
            }

            // got a _unique_ pair of column numbers
            if (! match) {
                uniq = &uniqlist[iter];
                uniq->lcol = lcol;
                uniq->rcol = rcol;
                break;
            }
        }

        // copy from one column to another
        for (int irow = 0;  irow < srch->maxrow;  ++irow)
            arr[irow][rcol] = arr[irow][lcol];

        printf("dojoin: EXPECTED %d,%d\n",lcol,rcol);
    }
}

// dotest -- perform test
void
dotest(int arr[MAXROW][MAXCOL])
{
    search_t srch;

    // NOTE: a smaller geometry can be used if desired
    search_init(&srch,MAXROW,MAXCOL);

    // create random matrix
    for (int irow = 0;  irow < srch.maxrow;  ++irow) {
        for (int icol = 0;  icol < srch.maxcol;  ++icol)
            arr[irow][icol] = rand();
    }

    // create columns that are the same
    dojoin(&srch,arr);

    // search entire matrix looking for matching columns
    for (int iter = 0;  iter < (opt_M * 2);  ++iter) {
        int match = search_find(&srch,arr);
        if (! match)
            break;

        printf("dotest: ACTUAL %d,%d\n",srch.lcol,srch.rcol);

        if (! search_next(&srch))
            break;
    }
}

int
main(int argc,char **argv)
{

    --argc;
    ++argv;

    for (;  argc > 0;  --argc, ++argv) {
        char *cp = *argv;
        if (*cp != '-')
            break;

        cp += 2;
        switch (cp[-1]) {
        case 'M':
            opt_M = (*cp != 0) ? atoi(cp) : (MAXCOL / 4);
            break;
        case 'R':
            opt_R = (*cp != 0) ? atoi(cp) : 1;
            break;
        }
    }

    // by printing the random seed value, and using -R on a subsequent program
    // invocation, we can make the result repeatable
    if (opt_R == 0)
        opt_R = time(NULL);
    printf("R: %u\n",opt_R);
    srand(opt_R);

    // set number of matching columns
    if (opt_M == 0)
        opt_M = 5;

    dotest(arrbig);

    return 0;
}

Here is the program output using -R1612382146. It has multiple columns that are the same:

R: 1612382146
dojoin: EXPECTED 12,99
dojoin: EXPECTED 2,74
dojoin: EXPECTED 18,91
dojoin: EXPECTED 18,34
dojoin: EXPECTED 64,93
dotest: ACTUAL 2,74
dotest: ACTUAL 12,99
dotest: ACTUAL 18,34
dotest: ACTUAL 18,91
dotest: ACTUAL 34,91
dotest: ACTUAL 64,93

Here are some more random outputs:

R: 1612387497
dojoin: EXPECTED 35,72
dojoin: EXPECTED 72,82
dojoin: EXPECTED 60,93
dojoin: EXPECTED 34,45
dojoin: EXPECTED 79,90
dotest: ACTUAL 34,45
dotest: ACTUAL 35,72
dotest: ACTUAL 35,82
dotest: ACTUAL 60,93
dotest: ACTUAL 72,82
dotest: ACTUAL 79,90

R: 1612387500
dojoin: EXPECTED 14,68
dojoin: EXPECTED 60,80
dojoin: EXPECTED 22,84
dojoin: EXPECTED 11,15
dojoin: EXPECTED 1,52
dotest: ACTUAL 1,52
dotest: ACTUAL 11,15
dotest: ACTUAL 14,68
dotest: ACTUAL 22,84
dotest: ACTUAL 60,80

R: 1612387503
dojoin: EXPECTED 40,42
dojoin: EXPECTED 16,29
dojoin: EXPECTED 8,69
dojoin: EXPECTED 23,74
dojoin: EXPECTED 44,67
dotest: ACTUAL 8,69
dotest: ACTUAL 16,29
dotest: ACTUAL 23,74
dotest: ACTUAL 40,42
dotest: ACTUAL 44,67

R: 1612387506
dojoin: EXPECTED 20,32
dojoin: EXPECTED 36,59
dojoin: EXPECTED 9,36
dojoin: EXPECTED 20,48
dojoin: EXPECTED 38,48
dotest: ACTUAL 9,36
dotest: ACTUAL 20,32
dotest: ACTUAL 38,48

R: 1612387508
dojoin: EXPECTED 40,71
dojoin: EXPECTED 34,84
dojoin: EXPECTED 53,72
dojoin: EXPECTED 8,73
dojoin: EXPECTED 17,75
dotest: ACTUAL 8,73
dotest: ACTUAL 17,75
dotest: ACTUAL 34,84
dotest: ACTUAL 40,71
dotest: ACTUAL 53,72

UPDATE:

Here's a version that puts all information into the struct so that a separate array pointer argument is not needed.

It uses a special "pointer to array" to help with multidimensional arrays of the form:

int (*arr)[MAXCOL];

See: C pointer to array/array of pointers disambiguation

This preserves the correct indexing for an array with arbitrary/dynamic array dimensions:

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

unsigned int opt_R;
int opt_M;
int opt_W;
int opt_H;

typedef struct {
    int maxrow;                         // maximum number of rows
    int maxcol;                         // maximum number of columns
    int *arr;                           // array base

    int lcol;                           // starting/current left column
    int rcol;                           // starting/current right column

    int match;                          // 1=match
} search_t;

#define ARRDEF \
    int (*arr)[srch->maxcol] = (__typeof__(arr)) srch->arr

#define MAXROW      100
#define MAXCOL      100

// search_init -- initialize for full matrix search
void
search_reset(search_t *srch)
{

    srch->lcol = 0;
    srch->rcol = 1;
}

// search_init -- initialize for full matrix search
search_t *
search_init(int maxrow,int maxcol)
{
    search_t *srch;

    srch = calloc(1,sizeof(*srch));

    srch->maxrow = maxrow;
    srch->maxcol = maxcol;

    srch->arr = malloc(sizeof(*srch->arr) * maxrow * maxcol);

    search_reset(srch);

    return srch;
}

// search_free -- free up array
void
search_free(search_t *srch)
{

    free(srch->arr);
    free(srch);
}

// search_match -- decide if two given columns match
// RETURNS: 1=match
int
search_match(const search_t *srch)
{
    ARRDEF;
    int match = 0;
    int lcol = srch->lcol;
    int rcol = srch->rcol;

    for (int irow = 0;  irow < srch->maxrow;  ++irow) {
        match = (arr[irow][lcol] == arr[irow][rcol]);
        if (! match)
            break;
    }

    return match;
}

// search_next -- advance to next search starting point
// RETURNS: 1=more to do
int
search_next(search_t *srch)
{
    int maxcol = srch->maxcol;

    srch->rcol += 1;

    if (srch->rcol >= maxcol) {
        srch->lcol += 1;
        srch->rcol = srch->lcol + 1;
    }

    return (srch->lcol < (maxcol - 1));
}

// search_find -- find next column pair that matches
int
search_find(search_t *srch)
{
    int maxcol = srch->maxcol;
    int match = 0;

    while (srch->lcol < (maxcol - 1)) {
        for (;  srch->rcol < maxcol;  ++srch->rcol) {
            match = search_match(srch);
            if (match)
                break;
        }
        if (match)
            break;

        if (! search_next(srch))
            break;
    }

    srch->match = match;

    return match;
}

// dojoin -- ensure unique pairing
void
dojoin(const search_t *srch)
{
    ARRDEF;
    int lcol;
    int rcol;
    search_t *uniq;
    search_t uniqlist[opt_M];

    // make certain columns identical
    for (int iter = 0;  iter < opt_M;  ++iter) {
        while (1) {
            // get two different column numbers
            while (1) {
                lcol = rand() % srch->maxcol;
                rcol = rand() % srch->maxcol;
                if (lcol != rcol)
                    break;
            }

            // we want low/high
            if (lcol > rcol) {
                int tmp = lcol;
                lcol = rcol;
                rcol = tmp;
            }

            // have we set this before?
            int match = 0;
            for (int uniqidx = 0;  uniqidx < iter;  ++uniqidx) {
                uniq = &uniqlist[uniqidx];
                match = ((lcol == uniq->lcol) && (rcol == uniq->rcol));
                if (match)
                    break;
            }

            // got a _unique_ pair of column numbers
            if (! match) {
                uniq = &uniqlist[iter];
                uniq->lcol = lcol;
                uniq->rcol = rcol;
                break;
            }
        }

        // copy from one column to another
        for (int irow = 0;  irow < srch->maxrow;  ++irow)
            arr[irow][rcol] = arr[irow][lcol];

        printf("dojoin: EXPECTED %d,%d\n",lcol,rcol);
    }
}

// dofill -- fill matrix
void
dofill(const search_t *srch)
{
    ARRDEF;

    for (int irow = 0;  irow < srch->maxrow;  ++irow) {
        for (int icol = 0;  icol < srch->maxcol;  ++icol)
            arr[irow][icol] = rand();
    }
}

// dotest -- perform test
void
dotest(int maxrow,int maxcol)
{
    search_t *srch;

    // NOTE: a smaller geometry can be used if desired
    srch = search_init(maxrow,maxcol);

    // create random matrix
    dofill(srch);

    // create columns that are the same
    dojoin(srch);

    // search entire matrix looking for matching columns
    for (int iter = 0;  iter < (opt_M * 2);  ++iter) {
        int match = search_find(srch);
        if (! match)
            break;

        printf("dotest: ACTUAL %d,%d\n",srch->lcol,srch->rcol);

        if (! search_next(srch))
            break;
    }

    search_free(srch);
}

int
main(int argc,char **argv)
{

    --argc;
    ++argv;

    for (;  argc > 0;  --argc, ++argv) {
        char *cp = *argv;
        if (*cp != '-')
            break;

        cp += 2;
        switch (cp[-1]) {
        case 'M':
            opt_M = (*cp != 0) ? atoi(cp) : (MAXCOL / 4);
            break;

        case 'R':
            opt_R = (*cp != 0) ? atoi(cp) : 1;
            break;

        case 'H':
            opt_H = atoi(cp);
            break;

        case 'W':
            opt_W = atoi(cp);
            break;
        }
    }

    // by printing the random seed value, and using -R on a subsequent program
    // invocation, we can make the result repeatable
    if (opt_R == 0)
        opt_R = time(NULL);
    printf("R: %u\n",opt_R);
    srand(opt_R);

    // set number of matching columns
    if (opt_M == 0)
        opt_M = 5;

    if (opt_H == 0)
        opt_H = MAXROW;
    if (opt_W == 0)
        opt_W = MAXCOL;
    dotest(opt_H,opt_W);

    return 0;
}
Craig Estey
  • 30,627
  • 4
  • 24
  • 48