Ricerca occorrenze in matrice

di Anonimizzato9570 il
44 risposte
Secondo voi perchè questa procedura mi sballa "legermente" il numero di occorrenze di un elemento in matrice?
considerate che ho usato una struct con i campi val e occ per gestire le occorrenze
void calcolaOccorrenze(matrice m,int r,int c, vettore & v,int rpm){
     
     int i=0;
     while(i<r){               
                    int occ=0;
                    for( int j=0;j<c-1;j++){
                    
                    for(int k=j+1;k<c;k++)
                    if(m[i][j]==m[i][k]){
                                         occ++;
                                         cout<<m[i][j];
                                         v[i].val=m[i][j];
                                         
                                         }
                    }
                        v[i].occ=occ;
                i++;
                }
                for (int p=0;p<c;p++)
                cout<<"il numero "<<v[p].val<<" si ripete "<<v[p].occ<<" volte \n";
}

44 Risposte

  • Ciao ^^,
    Allora non ho capito precisamente la traccia dell' esercizio però ti posso spiegare cosa fa questo programma che hai incollato:

    Data una riga i-esima della matrica inserisci nell' indirizzo i-esimo del vettore v l ' ultimo valore che abbia un' occorrenza e come occorenze il numero di volte che sono avvenute ( non di quel valore ma di tutti i possibili valori) . Esempio:

    una riga della matrice è formata dai seguenti numeri : 1 2 1 2
    Ci sono due occorenze ( 1 e 1 , 2 e 2 ) ma nel vettore inserirai solo l' ultimo valore che abbia un' occorrenza ( 2 ) quindi la stampa alla fine sarà:
    il valore 2 si ripete 2 volte ( penso sia questo l' errore che dici )

    Distinti Saluti,
    Alessandro
  • La traccia dice : data una matrice , calcolare il numero di occorrenze degli elementi su ogni riga

    in esecuzione ho il seguente risultato :
    
    la matrice è:
    3 5 5 5 6
    2 6 7 7 7 
    2 1 1 5 6 
    6 9 2 3 3
    3 3 3 3 4
    Gli elementi che si ripetono sono:
    55577713333333//<-------troppi 3 
    
    il numero 5  si ripete 3  volte
    il numero 7  si ripete  3 volte
    il numero 1  si ripete  1 volte
    il numero 3  si ripete  1  volte
    il numero 3  si ripete   6 volte
    
  • Eh si ho riletto secondo l' esempio della tua matrice ( ma non l' ho testato eseguendolo perchè mi scoccio di scrivere il programma xD ) comunque ti spiego quello che ho capito:

    Innanzitutto sono sbagliati anche gli altri perchè nella prima riga ( 5 5 5 ) ci sono due occorrenze e non tre.
    Il problema consiste nel fatto che fa lo stesso algoritmo partendo dall' elemento successivo , esempio con la prima riga:
    partiamo dalla seconda posizione ( j=1 ---> 5 ) m[0][1] == m[0][2]? si -> occ++ ( 1 )
    m[0][1] == m[0][3]) ? si - > occ++ ( 2 ) ; ora finisce il secondo ciclo e si incrementa il primo e quindi j = 2:
    m[0][2] == m[0][3] ? si ->> occ++ ( 3: ERRORE )

    Se fai lo stesso esempio con l' ultima riga vedi che ti spieghi il motivo per cui escono 6 occorrenze e non 3 . Quindi per cui penso che si possa risolvere in questo modo:
    
    void calcolaOccorrenze(matrice m,int r,int c, vettore & v,int rpm){
         
         int i=0;
         bool continuo= true;
         while(i<r)
         {               
               int occ=0;
               continuo=true;
               for( int j=0;j<c-1;j++)
               {
            	 if ( continuo )
                   for(int k=j+1;k<c;k++)
                      if(m[i][j]==m[i][k])
                      {
                          occ++;
                          cout<<m[i][j];
                          v[i].val=m[i][j];
                          continuo=false;
                      }
               }
               v[i].occ=occ;
               i++;
          }
          for (int p=0;p<c;p++)
                cout<<"il numero "<<v[p].val<<" si ripete "<<v[p].occ<<" volte \n";
    }
    
    Il problema ora ( e non risolto ) è quello che ti ho detto io prima: se ci fossero due occorrenze di valori diversi? ( esempio: 1 2 1 2 ) questo algoritmo non lo permetterà e ti darà errore semmai inserissi una matrice di questo tipo ^^.

    comunque sia controlla se funziona adesso

    DIstinti Saluti,
    Alessandro
  • XD avevo appena risolto, rivedendo MOLTO attentamente mi son accorto anchio di quest'errore, in ogni caso posto il codice funzionante
    void calcolaOccorrenze(matrice m,int r,int c, vettore & v,int rpm){
         
        int  i=0;
         while (i<r){
               bool trovato=false;
               int occ=1;
               for (int j=0;j<c-1;j++){
                   if(!trovato)
               for(int k=j+1;k<c;k++)
               if(m[i][j]==m[i][k]){                  
               occ++;
               trovato=true;}
               }
               
               cout<<"\n L'elemento sulla "<<i<<" riga si ripete "<<occ<<" volte ";
               i++;
               }
                    }
  • Ma se dovessi calcolare le occorrenze in tutta la matrice cosa mi suggerite?
    io avevo pensato ad una funzione booleana che verifica se un elemento è già presente, se si mi conta
    quante volte c'è.
    E' una soluzione conveniente?
  • Avrai bisogno di un vettore ( di struct sempre formato da valore e num_occ ) nel quale però non conosci il riempimento a priori ( prima invece lo conoscevi perchè coincideva con il numero di righe della matrice ) e quindi lo dovrai incrementare man mano che trovi un valore che ha suoi simili nella matrice. Per ogni i-esimo elemnto fai due cicli for che vanno a leggere tutti gli altri valori della matrice e metti la condizione per verificare l' occorrenza , però per far sì che non ricapiti il problema che avevi prima , per ogni i-esimo valore dovrai verificare che esso non si trovi nel vettore delle occorenze. Si può fare
  • Non ne riesco proprio a venire fuori, mi sto incasinando con il codice, ho scritto questa schifezza, credo che sia tutto sbagliato !
    
    void calcolaOccorrenzeInMatrice(matrice m,int r,int c, vettore & v,int rpm,int i,int j,int rip){
       
         int occ=0;
         for (int i=0;i<r;i++){
             for (int j=0;j<c-1;j++)
                 if(ePresente(m,r,c,i,j)){
                 conta(m,r,c,i,j,rip);             
                  v[i].val=m[i][j];
                  v[i].occ=rip;
                  }
         }
         for (int i=0;i<r;i++)
         cout<<" \n L'elemento "<<v[i].val<<" si ripete "<<v[i].occ<<" volte ";
    }
    
    bool ePresente(matrice m,int r,int c,int i,int j){
         
         for(int k=i;k<r;k++){
                 for(int q=j+1;j<c;j++)
                         if(m[i][j]==m[k][q]);
                          return true;
                         return false;
                 }
         
    }
    
    
    void conta(matrice m,int r,int c,int i, int j,int & rip){
        rip=0;
         for(int p=i;i<r;i++)
         for (int q=j;j<r;j++)
         if(m[i][j]==m[p][q])
         rip++;
         }
    
    
    
  • E' più complesso, comunque incomincio a dirti che ci sono molti parametri che passi nella funzione calcolaOccorrenzeInMatrice che puoi anche non passare : int i , int j , int rip e poi int rpm dove viene utilizzato?

    Oltre questo allora il discorso è che oltre alla condizione ePresente deve anche verificare che quel valore non deve essere prensente nel vettore v ( perchè per quel valore hai già calcolato le occorrenze ). Poi il conta non devi farlo partire dalla posizione [j] ma devi sempre farlo partire da [0][0] soltanto che nel ciclo devi imporre un if del tipo:
    
    void conta(matrice m,int r,int c,int i, int j,int & rip){
        rip=0;
         for(int p=0;i<r;i++)
            for (int q=0;j<c;j++)
            {
               if ( p== i && q == j )  // se questo elemento è uguale a quello che stai calcolando allora non                         fare niente
               else
                   if( m[i][j]==m[p][q])
                         rip++;
            }
     }
    
  • Anzi ora che ci penso quello che ti ho scritto può essere sbagliato perchè ti faccio fare più cicli inutili , quindi è meglio iniziare dalla posizione i e j ^^. Comunque penso che la funzione ePresente non serva più di tanto perchè fai fare solo più cicli quando invece ne fai solo uno in conta ( uno inteso come due for xD ) . Penso ti basti solo una funzione che ti restituisca true se il valore esiste nel vettore altrimenti false e se non esiste nel vettore allora li conti e se il conta risulta essere > 0 allora esiste una occorrenza e la inserisci nel vettore. Di conseguenza prevedo una funzione conta che restituisca un intero ( in questo modo non devi passare come parametro rip ). Non so se sono stato chiaro , altrimenti ti faccio una bozza
  • 
    void calcolaOccorrenzeInMatrice(matrice m,int r,int c, vettore & v,int & riemp_v){
       
         int occ=0;
         int cont;
         for (int i=0;i<r;i++)
         {
             for (int j=0;j<c-1;j++)
                 if( !ePresente(m[i][j],v,riemp_v) ) // se il valore non è presente nel vettore esegui l' istruzione
                 {
                	cont = conta(m,r,c,i,j); // conta il numero di occorrenze
                    if ( cont > 0 ) // se > 0 allora inserisce nel vettore
                    {
                        v[riemp_v].val=m[i][j];
                        v[riemp_v].occ=cont;
                        riemp_v++; // incrementa il riempimento del vettore
                    }
                 }
         }
         for (int i=0;i<riemp_v;i++)
         cout<<" \n L'elemento "<<v[i].val<<" si ripete "<<v[i].occ<<" volte ";
    }
    
    bool ePresente(int numero,vettore v, int riemp_v){
         
       for ( int i = 0 ; i < riemp_v ; i++)
    	   if ( numero == v[i].val )
    		   return true;
       return false;   
    }
    
    
    int conta(matrice m,int r,int c,int i, int j){
        int rip=0;
        for(int p=i;i<r;i++)
           for (int q=j;j<c;j++)
              if(m[i][j]==m[p][q])
                   rip++;
        return rip;
    }
    
    Non ho compilato nè niente, è giusto per farti capire l' idea che ho in mente .
  • Beh effettivamente non avevo compilato è stato una cosa che ho buttato giù . Comunque io gli passo
    
    !ePresente(m[i][j],v,riemp_v)
    
    Nel tuo
    
    bool ePresente (matrice m,int r,int c,int i,int j,vettore v,int rpm)
    .....
     while (!ePresente (m,r,c,i,j,rpm)) 
    
    sbagli a passargli i parametri , ti sei dimenticato di passargli il vettore.
  • Ho provato così:
    
    void ricercaOccorrenze(matrice m,int r, int c, int i, int j,vettore & v,int & rpm){
         rpm=0;
           for(int i=0;i<r;i++){
                  for (int j=0;j<c;j++){ //per ogni elemento della matrice
                  int occ=0;
                        while (!ePresente (m,r,c,i,j,v,rpm)){// se non è presente nell'array degli elementi ripetuti
                               for(int p=0;p<r;p++)
                                       while(j<c-1)
                                            for (int q=j+1;q<c;q++)
                                                     if (m[i][j]==m[p][q]){
                                                      occ++;
                                                       v[rpm].val=m[i][j];
                                                       v[rpm].occ=occ;
                                                       rpm++;
                                                     }
                                                     cout<<prova;//<--------------------------non entra nel ciclo 
                        } 
                  }
           }
           for ( int i=0;i<rpm;i++)
           cout<<v[i].val;
    }
    
    
    bool ePresente (matrice m,int r,int c,int i,int j,vettore v,int rpm){
        
        for (int i=0;i<rpm;i++)
        if (v[i].val==m[i][j])
        return true;
        return false;
    }
    
    ma dove segnalato, non entra nel ciclo
  • Cerca di indentare meglio tipo così , in modo tale che capisci il cout<<prova ( ma poi prova dove è dichiarato? ) in quale blocco di istruzione si trova e se l' hai messo nel posto dove volevi
    
    void ricercaOccorrenze(matrice m,int r, int c, int i, int j,vettore & v,int & rpm){
         rpm=0;
         for(int i=0;i<r;i++)
         {
             for (int j=0;j<c;j++)
             { //per ogni elemento della matrice
                  int occ=0;
                  while (!ePresente (m,r,c,i,j,v,rpm))
                  {// se non è presente nell'array degli elementi ripetuti
                      for(int p=0;p<r;p++)
                            while(j<c-1)
                                for (int q=j+1;q<c;q++)
                                       if (m[i][j]==m[p][q])
                                       {
                                            occ++;
                                            v[rpm].val=m[i][j];
                                            v[rpm].occ=occ;
                                            rpm++;
                                       }
                      cout<<prova;//<--------------------------non entra nel ciclo 
                  } 
             }
         }
         for ( int i=0;i<rpm;i++)
             cout<<v[i].val;
    }
    
    Forse non hai capito bene la funzione ePresente come l' ho definita io:
    allora il programma l' ho pensato così : Per ogni elemento [j] della matrice controlla se si trova nel vettore v ( questa è la funzione ePresente ) , se non si trova allora conta quante occorenze trova rispetto al valore [j] , se il conta è > 0 ( e quindi ha trovato almeno una occorrenza ) allora lo inserisce nel vettore v e incrementa il riemp.
    
     while (!ePresente (m,r,c,i,j,v,rpm))
    

    perchè un while ? il controllo per ogni elemento lo deve fare una volta quindi penso sia corretto if.
  • Guarda ho provato su un array
    
    void calcolaOccorrenze(vettore v,int r, int i, vett & v2,int & rpm){
                        bool riemp = false;
                        bool inserisci =false;
                        rpm=0;   
                        for ( i=0;i<r-1;i++){
                              int occ=0;
                         if(!ePresente( v, r, i, v2,rpm))
                            for (int j=i+1;j<r;j++){
                                if (v[i]==v[j]){
                                   cout<<v[i]<<" occ++\n";
                                    inserisci=true;
                                    riemp=true;
                                    occ++;
                                    }
                                if (inserisci)<--------------------// questi due mi danno problemi, ma non capisco il motivo
                                v2[rpm].val=v[i];
                                v2[rpm].occ=occ;
                                if(riemp)<-------------------------
                                rpm++;
                                
                            }
                            
                        }    
                for (int p=0;p<rpm;p++)
                cout<<v2[p].val;    
                      
    }
    
    
    bool ePresente(vettore v, int r, int i,vett v2,int rpm){
         for ( int p=0;p<rpm;p++)
         if (v2[p].val==v[i]){
             return true;
         }
         
         return false;
         
         }
    
    funziona al 30% nel senso che il problema adesso sta nell'aumento di rpm e inserisci
Devi accedere o registrarti per scrivere nel forum
44 risposte