Función que diga si dos columnas/filas de una matriz son iguales.

Iniciado por hackersanfe, 4 Diciembre 2018, 19:10 PM

0 Miembros y 2 Visitantes están viendo este tema.

hackersanfe

Buenas tardes, estoy intentando realizar esta función en C, sin embargo no se me ocurre la manera correcta de llegar a ella. Concretamente mi ejercicio es:

"Escribe un programa, que en primer lugar, genere una matriz de NxM elementos enteros con números aleatorios comprendidos entre 1 y 20 (N y M constantes enteras globales).
El programa además de generar la matriz, deberá escribir sus valores y escribir un mensaje indicando si hay o no dos columnas iguales en la matriz, en caso de no haberlas, solo en ese caso, deberá escribir un mensaje indicando si hay o no dos filas iguales en la matriz. Si no hubiera ni dos filas iguales, ni dos columnas iguales escribirá un mensaje indicándolo.
También escribirá el valor máximo y la fila y columna en la que se encuentra la primera aparición del valor máximo (haciendo un recorrido por filas)."

Se trata de una función de NxM.
Si me podeis dar una idea de como seria el hacerla me ayudariais un monton. Porque en mi cabeza parece facil (y seguro que lo es) pero no llego a ello... un saludo y gracias por cualquier ayuda recibida.
#include<stdlib.h>
#include<time.h>
#include <stdio.h>
#define N 3
#define M 6

void escribirMat (int mat[N][M]);
void generaMat (int mat[N][M]);
void matrizMaxPos (int mat[N][M], int *max, int *fil, int *col);
int columnasIguales(int mat[N][M]);


int main()
{
   int mat[N][M];
   int *max=0,*fila=0,*columna=0;
   generaMat(mat);
   escribirMat(mat);
   matrizMaxPos(mat,&max,&fila,&columna);
   printf("\nMaximo: %d y aparece por primera vez en la fila %d y columna %d.\n",max,fila,columna);
   if(columnasIguales(mat)==1){
       printf("\nHay al menos dos columnas iguales.\n");
   }
   else printf("\nNinguna columna igual.\n");
   return 0;
}


void generaMat(int mat[N][M])
{
   int f,c;
   srand(time(NULL));
   for(f=0; f<N; f++)
       for(c=0; c<M; c++)
           mat[f][c]=rand()%20+1;
}

void matrizMaxPos (int mat[N][M], int *max, int *fil, int *col){
   int i,j,enc=0;
   for(i=0;i<N;i++){
       for(j=0;j<M;j++){
           if(*max<mat[i][j])
               *max=mat[i][j];
       }
   }
   for(i=0;i<N;i++){
       for(j=0;j<M;j++){
           if(*max==mat[i][j]&&!enc){
               *fil=i+1;
               *col=j+1;
               enc=1;
           }
       }
   }
}

int columnasIguales(int mat[N][M]){
   int i=0,j=0,iguales=0;
   if((mat[i][j]==mat[i][j+1]&&i<N-1&&j<M-1)&&(mat[i+1][j]==mat[i+1][j+1]&&i<N-1&&j<M-1)&&(mat[i+2][j]==mat[i+2][j+1]&&i<N-1&&j<M-1))
       iguales=1;
   else{
       i++;
       j++;
   }
   return iguales;
}

void escribirMat (int mat[N][M]){
   int i,j;
   for(i=0;i<N;i++){
       for(j=0;j<M;j++){
           printf("%d ", mat[i][j]);
       }
       printf("\n");
   }
}

K-YreX

Especifica qué parte es la que no sabes implementar... si es desde meter los valores en la matriz o comparar dos filas o columnas...
Y si tienes algo de código hecho ponlo también en el mensaje para que lo veamos. :-X
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

hackersanfe

Cita de: YreX-DwX en  4 Diciembre 2018, 19:14 PM
Especifica qué parte es la que no sabes implementar... si es desde meter los valores en la matriz o comparar dos filas o columnas...
Y si tienes algo de código hecho ponlo también en el mensaje para que lo veamos. :-X
Ya está compañero.
Especificamente lo que no se implementar es la comparacion de la primera columna con la segunda, la primera con la tercera, la primera con la cuarta... hasta que se hayan comparado todas con todas. La funcion que aparece ahi de columnas iguales no me funciona por cierto, es lo que intente yo pero nada.

K-YreX

#3
Primero tienes que cambiar la declaración siguiente:

int *max=0,*fila=0,*columna=0;

No tienes que declararlos como punteros si luego los pasas a la función usando "&".

Ahora la función, por ejemplo una forma de comparar cada columna de una forma visual es la siguiente:

int compararColumnas(int matriz[FILAS][COLUMNAS]){
int iguales = 0;
int columnaAComparar[FILAS];

for(int i = 0; i < COLUMNAS-1 && !iguales; i++){
for(int j = 0; j < FILAS; j++) // copiamos la columna a comparar en columnaAComparar
columnaAComparar[j] = matriz[j][i];

for(int m = i+1; m < COLUMNAS && !iguales; m++){ // para cada columna en adelante, mientras no sean iguales...
iguales = 1; // ...suponemos que la columna m es igual a la columna i guardada en columnaAComparar
for(int n = 0; n < FILAS && iguales; n++) // recorremos la columna m mientras no lleguemos al final y sean iguales
if(matriz[n][m] != columnaAComparar[n])
iguales = 0;
}
}
return iguales;
}


También puedes ahorrarte el copiar la columna a comparar en cada iteración. Así ganas eficiencia aunque se ve peor por eso para que lo veas bien te lo dejo así y ya tú cuando lo entiendas puedes cambiarlo para no tener que usar un array auxiliar. Suerte.
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

hackersanfe

Muchisimas gracias, la verdad es que aunque exista otra manera mas eficiente de hacerla, esa me parece clarisima. Gracias de verdad. ;-)

CalgaryCorpus

Me gusto la solucion propuesta.

Mientras la miraba se me ocurrio otra, pero es definitivamente mas complicada, asi que la presento solo para incluir una idea adicional.

Si uno mantiene adicionalmente algun valor para cada columna / fila (por ejemplo la suma de los elementos), se puede descartar rapidamente si una fila es candidata a ser igual a otra.

  1   2   3  4
  4   5   6  8
  7   8   9  0
[12  15  18  12]  <-- sumas



Solo es necesario comparar la 1a y 4ta columna.
Lo que significa para el codigo propuesto es hacer 1 comparacion que controle si hay que hacer el ciclo for de la linea 11 o no.

La modificacion es, en la linea 10, cambiar la asignacion y hacer:
             iguales = (sumas[i] == sumas[m]);

El arreglo sumas se crea en generaMat.

Aqui mi perfil en LinkedIn, invitame un cafe aqui

hackersanfe

Cita de: CalgaryCorpus en  5 Diciembre 2018, 02:05 AM
Me gusto la solucion propuesta.

Mientras la miraba se me ocurrio otra, pero es definitivamente mas complicada, asi que la presento solo para incluir una idea adicional.

Si uno mantiene adicionalmente algun valor para cada columna / fila (por ejemplo la suma de los elementos), se puede descartar rapidamente si una fila es candidata a ser igual a otra.

 1   2   3  4
 4   5   6  8
 7   8   9  0
[12  15  18  12]  <-- sumas



Solo es necesario comparar la 1a y 4ta columna.
Lo que significa para el codigo propuesto es hacer 1 comparacion que controle si hay que hacer el ciclo for de la linea 11 o no.

La modificacion es, en la linea 10, cambiar la asignacion y hacer:
            iguales = (sumas[i] == sumas[m]);

El arreglo sumas se crea en generaMat.


Claro, es una implementacion un poco mas complicada en mi opinion, pero tambien seria valida.
Ahora estoy intentando hacer que me funcione el modelo que paso el compañero para que haga lo mismo con las filas, de momento no lo estoy consiguiendo, esto es lo que he hecho:
int compararFilas(int mat[N][M])
{
   int iguales=0,i,j,m,n;
   int filaAComparar[N];
   for(i=0; i<N-1&&!iguales; i++)
   {
       for(j=0; j<M; j++)
           filaAComparar[j]=mat[j][i];

       for(m=i+1; m<M; m++)
      {
           iguales=1;
           for(n=0; n<N&&iguales; n++) /
               if(mat[n][m]!=filaAComparar[n])
                   iguales=0;
       }


   }
   return iguales;
}

K-YreX

#7
Tienes que ver qué índice representa a las filas y qué índice a las columnas. No vale eso de coger un código cambiarle el nombre y que haga otra cosa.
Edit: Además mira a ver cuál debería ser el tamaño de tu array auxiliar... Suerte.
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

CalgaryCorpus

Parece que la logica original hay que modifcarla un poco, pues si existen 2 coliumnas iguales, pero justo las ultimas 2 que se comparan no son iguales, la funcion va a retornar 0.

Es lo que se quiere?
Aqui mi perfil en LinkedIn, invitame un cafe aqui

K-YreX

#9
Cita de: CalgaryCorpus en  5 Diciembre 2018, 19:36 PM
Parece que la logica original hay que modifcarla un poco, pues si existen 2 coliumnas iguales, pero justo las ultimas 2 que se comparan no son iguales, la funcion va a retornar 0.

Es lo que se quiere?

Es cierto, faltaría meterle la condición de que no sean iguales a uno de los <for> para que en cuanto haya dos iguales salga del todo. Fallo mío :-X Con estas correcciones ya debería funcionar. :silbar:
Edit: Ya está modificado el código original (creo que no tiene más fallos, si alguien encuentra alguno que me lo comente). Y Hackersanfe, te recomiendo que lo pienses por ti mismo, el reto está en conseguir hacerlo funcionar sin mirar la solución, mirándola es muy fácil.
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;