# Esercitazione 5: Typedef e Matrici # Dati Anagrafici Si definisca un tipo di dato `DatiArchivio` contenente i seguenti dati relativi ad una persona: * Età * Altezza * Peso **Richieste** 1. Si scriva un programma in grado di memorizzare i dati relativi a 5 persone inseriti dall’utente 2. Si stampino tutti i dati anagrafici inseriti 3. Si stampino i dati anagrafici relativi a persone con al più 20 anni 4. Si stampi l’altezza media di tutti dati inseriti 5. Si stampi l’altezza media dei soli dati inseriti relativi a persone con almeno 30 anni ```c #include <stdio.h> #define N 5 int main(int argc, char* argv[]) { // Tipo typedef struct { int eta; int altezza; int peso; } DatiArchivio; // Variabili DatiArchivio persone[N]; int i, n_30_anni; float a_media; // Acquisizione dati for(i=0; i<N; i++){ printf("Persona %d\n", i+1); do { printf("Inserisci età: "); scanf("%d", &persone[i].eta); } while(persone[i].eta < 0); do { printf("Inserisci altezza: "); scanf("%d", &persone[i].altezza); } while(persone[i].altezza < 0); do { printf("Inserisci peso: "); scanf("%d", &persone[i].peso); } while(persone[i].peso < 0); } // Stampa di tutti i dati printf("\nTUTTI\n"); for(i=0; i<N; i++) printf("Persona %d: età = %d - altezza = %d - peso = %d\n", i+1, persone[i].eta, persone[i].altezza, persone[i].peso); // Stampa di dati con età <= 20 printf("\nPERSONE CON ETA <= 20\n"); for(i=0; i<N; i++){ if(persone[i].eta <= 20) printf("Persona %d: età = %d - altezza = %d - peso = %d\n", i+1, persone[i].eta, persone[i].altezza, persone[i].peso); } // Altezza media di tutti printf("\nALTEZZA MEDIA di TUTTI\n"); a_media = 0; for(i=0; i<N; i++) a_media += persone[i].altezza; a_media /= N; printf("Altezza media: %.2f\n", a_media); // Altezza media di persone con anni >= 30 printf("\nALTEZZA MEDIA di PERSONE CON ETA >= 30\n"); a_media = 0; n_30_anni = 0; for(i=0; i<N; i++){ if(persone[i].eta >= 30){ a_media += persone[i].altezza; n_30_anni++; } } a_media /= n_30_anni; printf("Altezza media di persone con almeno 30 anni: %.2f\n", a_media); return 0; } ``` --- # Confronto Articoli Si definisca un tipo di dato `Articolo` composto dai seguenti campi: * Titolo (stringa con spazi) * Numero di Citazioni (int) * Numero di Autori (int) * Cognome Autore Principale (stringa no spazi) **Richieste** 1. Si scriva un programma in grado di memorizzare i dati relativi a 5 articoli, da dati inseriti dall’utente 1. Si stampi il cognome dell’autore principale dell’articolo con il titolo più lungo tra quelli inseriti 1. Si inizializzi staticamente (i.e., direttamente nel codice) una variabile articolo con i seguenti valori nei rispettivi campi: * Titolo: “An Amazing Research” * N. Citazoni: 1000 * N. Autori: 5 * Cognome Autore Principale: “Montenegro” 1. Per ogni articolo inserito dall’utente, stampare i dati dei soli articoli con un numero di citazioni maggiori o uguali a quelle dell’articolo inizializzato staticamente 1. Si modifichi la struttura in modo tale che si salvi anche la lista dei cognomi degli autori (senza ripetere l’autore principale) 1. Si stampi il numero di autori medio degli articoli inseriti dall’utente con autore principale 1. Si stampi il numero di autori medio degli articoli inseriti dall’utente aventi almeno un autore in comune con l’articolo inizializzato staticamente ```c #include <stdio.h> #include <string.h> #define N 5 #define LEN 100 int main(int argc, char* argv[]) { // Tipo typedef char stringa[LEN]; typedef struct { stringa titolo; int n_cit; int n_autori; stringa autore; stringa altri_autori[LEN]; } Articolo; // Variabili Articolo articoli[N], articolo_statico; int i, idx_titolo_lungo, max_len, j, n_aut_medio_N; float n_aut_medio; // Acquisizione dati for (i=0; i<N; i++) { printf("Dati articolo %d\n", i+1); printf("Titolo: "); gets(articoli[i].titolo); do { printf("Citazioni: "); scanf("%d", &articoli[i].n_cit); } while(articoli[i].n_cit < 0); do { printf("Numero di Autori: "); scanf("%d", &articoli[i].n_autori); } while(articoli[i].n_autori < 0); printf("Cognome Autore Principale: "); scanf("%s", articoli[i].autore); fflush(stdin); // serve per evitare che la prossima gets legga quello che rimane nel buffer // !! non sappiamo come si comporta l'utente !! for(j=0; j<articoli[i].n_autori-1; j++){ do { printf("Cognome Co-Autore %d: ", j+1); scanf("%s", articoli[i].altri_autori[j]); fflush(stdin); } while(!strcmp(articoli[i].autore, articoli[i].altri_autori[j])); } } // Stampo titolo più lungo max_len = 0; idx_titolo_lungo = 0; for(i=0; i<N; i++){ if(strlen(articoli[i].titolo) > max_len){ idx_titolo_lungo = i; max_len = strlen(articoli[i].titolo); } } printf("\n'%s' ha il titolo più lungo\n", articoli[idx_titolo_lungo].titolo); // Inizializzo l'articolo statico strcpy(articolo_statico.titolo, "An Amazing Research"); articolo_statico.n_cit = 1000; articolo_statico.n_autori = 1; strcpy(articolo_statico.autore, "Montenegro"); // Stampo Dati di articoli con più citazioni dell'articolo statico printf("\nARTICOLI CON PIU CIT DELL'ARTICOLO STATICO\n"); for(i=0; i<N; i++){ if(articoli[i].n_cit > articolo_statico.n_cit){ printf("Titolo: %s\nCitazioni: %d\nN. Autori: %d\nAutore: %s\n", articoli[i].titolo, articoli[i].n_cit, articoli[i].n_autori, articoli[i].autore); for(j=0; j<articoli[i].n_autori-1; j++){ printf("Co-Autore %d: %s\n", j+1, articoli[i].altri_autori[j]); } } } // Stampo il numero medio di autori printf("\nN. AUTORI MEDIO\n"); n_aut_medio = 0; n_aut_medio_N = 0; for(i=0; i<N; i++){ n_aut_medio += articoli[i].n_autori; } n_aut_medio /= N; printf("%.2f\n", n_aut_medio); // Stampo il numero medio di autori di articoli in cui ha partecipato Montenegro printf("\nN. AUTORI MEDIO DI ARTICOLI IN CUI HA PARTECIPATO MONTENEGRO\n"); n_aut_medio = 0; n_aut_medio_N = 0; for(i=0; i<N; i++){ if(!strcmp(articolo_statico.autore, articoli[i].autore)){ n_aut_medio += articoli[i].n_autori; n_aut_medio_N++; } else{ for(j=0; j<articoli[i].n_autori-1; j++){ if(!strcmp(articolo_statico.autore, articoli[i].altri_autori[j])){ n_aut_medio += articoli[i].n_autori; n_aut_medio_N++; } } } } n_aut_medio /= n_aut_medio_N; printf("%.2f\n", n_aut_medio); return 0; } ``` --- # Confronto Studenti Si definisca un tipo di dato `Studente` composto dai seguenti campi: * Nome (stringa no spazi) * Cognome (stringa no spazi) * Età * Sigla corso di iscrizione (stringa di 3 lettere a scelta tra “AUT”, “INF”, o “MAT”) * Media voti **Richieste** 1. Si scriva un programma in grado di memorizzare i dati relativi a 5 studenti inseriti dall’utente 1. Si stampi l’età media di tutti gli studenti 1. Si stampi l’età media di tutti gli studenti iscritti a “MAT” 1. Si stampi il nome e il cognome dello studente con la media più alta tra quelli iscritti a “INF” 1. Si modifichi la struttura in modo tale da aggiungere un campo `ultimitrevoti` che sia un array di dimensione 3 che salvi gli ultimi 3 voti registrati dallo studente. Si modifichi, se necessario, il codice scritto finora 1. Si stampino il nome ed il cognome di tutti gli studenti di “AUT” che abbiano come ultimi 3 voti registrati tutti voti maggiori o uguali di 29 ```c #include <stdio.h> #include <string.h> #define N 5 #define LEN 100 int main(int argc, char* argv[]) { // Tipo typedef char stringa[LEN]; typedef struct { stringa nome; stringa cognome; int eta; char corso[4]; float media; float ultimi_voti[3]; } Studente; // Variabili Studente studenti[N]; int i, eta_media_N, idx_max_media, j, flag; float eta_media, max_media; // Acquisizione for(i=0; i<N; i++){ printf("Studente %d\n", i+1); printf("Nome: "); scanf("%s", studenti[i].nome); fflush(stdin); printf("Cognome: "); scanf("%s", studenti[i].cognome); fflush(stdin); do { printf("Età: "); scanf("%d", &studenti[i].eta); } while(studenti[i].eta < 0); do { printf("Corso (AUT - INF - MAT): "); scanf("%s", studenti[i].corso); fflush(stdin); } while (strcmp(studenti[i].corso, "AUT") && strcmp(studenti[i].corso, "INF") && strcmp(studenti[i].corso, "MAT")); do { printf("Media: "); scanf("%f", &studenti[i].media); } while(studenti[i].media < 0 && studenti[i].media > 32); for (j=0; j<3; j++) { do { printf("Voto %d: ", j+1); scanf("%f", &studenti[i].ultimi_voti[j]); } while(studenti[i].ultimi_voti[j] < 0 && studenti[i].ultimi_voti[j] > 32); } } // Stampo età media di tutti printf("\nETA MEDIA\n"); eta_media = 0; for(i=0; i<N; i++){ eta_media += studenti[i].eta; } eta_media /= N; printf("%.2f", eta_media); // Stampo età media degli studenti MAT printf("\nETA MEDIA MAT\n"); eta_media = 0; eta_media_N = 0; for(i=0; i<N; i++){ if(!strcmp(studenti[i].corso, "MAT")){ eta_media += studenti[i].eta; eta_media_N++; } } eta_media /= eta_media_N; printf("%.2f", eta_media); // Stampo nome e cognome dello studente INF con media più alta printf("\nSTUDENTE INF CON MEDIA PIù ALTA\n"); max_media = 0; idx_max_media = -1; for(i=0; i<N; i++){ if(!strcmp(studenti[i].corso, "INF") && studenti[i].media > max_media){ max_media = studenti[i].media; idx_max_media = i; } } if(idx_max_media != -1) printf("%s - %s\n", studenti[idx_max_media].nome, studenti[idx_max_media].cognome); else printf("No studenti INF"); // Stampo nome e cognome degli studenti AUT con ultimi voti tutti >= 29 printf("\nSTUDENTE AUT CON ULTIMI VOTI SOPRA AL 29\n"); for(i=0; i<N; i++){ if(!strcmp(studenti[i].corso, "AUT")){ flag = 0; for(j=0; j<3 && flag != 1; j++){ if(studenti[i].ultimi_voti[j] < 29) flag = 1; } if(!flag) printf("%s - %s\n", studenti[i].nome, studenti[i].cognome); } } return 0; } ``` --- # Traccia e Trasposta **Testo** Si scriva un programma in grado di popolare una matrice quadrata di dimensione NxN. Durante l’inserimento, programma inserisce il valore assoluto del numero inserito dall’utente Si stampi la traccia della matrice (i.e., la somma delle componenti sulla diagonale principale) Si stampi la matrice trasposta **Esempio** $A = \left[\begin{matrix} 1 & 2 & 3 \\ 4 & 5 & 6 \\ 7 & 8 & 9 \end{matrix}\right]$ $Trace(A) = \sum_{i=0}^{N-1}A_{i,i} = 1 + 5 + 9 = 15$ $A^{\top} = \left[\begin{matrix} 1 & 4 & 7 \\ 2 & 5 & 8 \\ 3 & 6 & 9 \end{matrix}\right]$ ## Versione Base ```c #include <stdio.h> #define N 3 int main(int argc, char* argv[]) { // Variabili int mat[N][N], mat_T[N][N], i, j, traccia; // Popolamento matrice solo con valori assoluti for(i=0; i<N; i++){ for(j=0; j<N; j++){ printf("Inserire elemento mat[%d][%d]: ", i, j); scanf("%d", &mat[i][j]); // prendo l'opposto se necessario if(mat[i][j] < 0) mat[i][j] = -mat[i][j]; } } // Calcolo traccia traccia = 0; for(i=0; i<N; i++){ traccia += mat[i][i]; } printf("Traccia: %d\n", traccia); // Traspongo for(i=0; i<N; i++){ for(j=0; j<N; j++){ mat_T[i][j] = mat[j][i]; } } // Stampo trasposta for(i=0; i<N; i++){ for(j=0; j<N; j++){ printf("%d ", mat_T[i][j]); } printf("\n"); } return 0; } ``` ## Versione Ottimizzata ```c #include <stdio.h> #define N 3 int main(int argc, char* argv[]) { // Variabili int mat[N][N], mat_T[N][N], i, j, traccia; // Popolamento matrice solo con valori assoluti traccia = 0; for(i=0; i<N; i++){ for(j=0; j<N; j++){ printf("Inserire elemento mat[%d][%d]: ", i, j); scanf("%d", &mat[i][j]); // prendo l'opposto se necessario if(mat[i][j] < 0) mat[i][j] = -mat[i][j]; // Calcolo traccia if(i == j) traccia += mat[i][j]; // popolo trasposta mat_T[j][i] = mat[i][j]; } } printf("Traccia: %d\n", traccia); // Stampo trasposta for(i=0; i<N; i++){ for(j=0; j<N; j++){ printf("%d ", mat_T[i][j]); } printf("\n"); } return 0; } ``` --- # Matrice Diagonalmente Dominante Una matrice quadrata si dice diagonalmente dominante se, per ogni riga, la somma dei valori assoluti degli elementi della riga, escluso l’elemento delle riga sulla diagonale principale, è minore del valore assoluto dell’elemento sulla diagonale principale della riga. Scrivere un programma che permetta di inserire i valori di una matrice NxN e che verifichi se sia dominante o meno. **Esempio** $\left[\begin{matrix} 10 & 1 & -2\\ -1 & 10 & 2\\ 3 & 5 & 10 \end{matrix}\right]$ è dominante $\left[\begin{matrix} 10 & 1 & -2\\ -15 & 10 & 2\\ 3 & 25 & 10 \end{matrix}\right]$ NON è dominante ```c // Librerie #include <stdio.h> // MACRO #define N 3 int main(int argc, char* argv[]) { // Variabili int mat[N][N], i, j, somma, abs, flag = 0; // Acquisizione Matrice for(i=0; i<N; i++){ for(j=0; j<N; j++){ printf("Inserire l'elemento in riga %d e colonna %d: ", i+1, j+1); scanf("%d", &mat[i][j]); } } // Verifica che sia diagonalmente dominante for(i=0; i<N; i++){ // sommo i valori assoluti degli elementi tranne che di mat[i][i] somma = 0; for (j=0; j<N; j++) { if(i!=j){ abs = mat[i][j]; if(abs<0) abs = -abs; somma += abs; } } // prendo il valore assoluto di mat[i][i] abs = mat[i][i]; if(abs < 0) abs = -abs; // controllo se non è dominante if(somma > abs){ flag = 1; break; } } // Stampa Matrice if(flag) printf("Non dominante\n"); else printf("Dominante\n"); return 0; } ``` --- # Prodotto di Kronecker Il prodotto di Kronecker tra una matrice A (NxM) e B (PxQ) è una matrice (NxP)x(MxQ) definita come: ![Screenshot_2024-10-17_alle_16.46.28](https://hackmd.io/_uploads/rkwzeDGlkx.png) Scrivere un programma che richieda l’inserimento di valori nelle matrici A e B, che calcoli il prodotto di Kronecker e lo stampi. ```c // Librerie #include <stdio.h> // MACRO #define N 3 #define M 3 #define P 3 #define Q 3 int main(int argc, char* argv[]) { // Variabili int a[N][M], b[P][Q], p[N*P][M*Q], i, j, k, t; // Acquisizione Matrici for(i=0; i<N; i++){ for(j=0; j<M; j++){ printf("Inserire l'elemento di A in riga %d e colonna %d: ", i+1, j+1); scanf("%d", &a[i][j]); } } for(i=0; i<P; i++){ for(j=0; j<Q; j++){ printf("Inserire l'elemento di B in riga %d e colonna %d: ", i+1, j+1); scanf("%d", &b[i][j]); } } // Prodotto di Kronecker for(i=0; i<N; i++){ for(j=0; j<M; j++){ for(k=0; k<P; k++){ for(t=0; t<Q; t++){ p[i*P + k][j*Q + t] = a[i][j] * b[k][t]; } } } } // Stampo prodotto for(i=0; i<N*P; i++){ for(j=0; j<M*Q; j++){ printf(" %d", p[i][j]); } printf("\n"); } return 0; } ``` --- # Numero di Claque Una claque di una matrice NxM è una sottomatrice 2x2 tale che la somma degli elementi della sua diagonale principale sia uguale alla somma degli elementi della contro-diagonale. Si scriva un programma che prenda in input una matrice e che stampi il numero di claque della matrice stessa. ![Screenshot_2024-10-17_alle_17.12.16](https://hackmd.io/_uploads/SJjQlwflyg.png) ```c // Librerie #include <stdio.h> // MACRO #define N 3 #define M 3 int main(int argc, char* argv[]) { // Variabili int a[N][M], i, j, somma1, somma2, n_claque = 0; // Acquisizione Matrice for(i=0; i<N; i++){ for(j=0; j<M; j++){ printf("Inserire l'elemento di A in riga %d e colonna %d: ", i+1, j+1); scanf("%d", &a[i][j]); } } // Conto Claque for(i=0; i<N-1; i++){ for(j=0; j<M-1; j++){ somma1 = a[i][j] + a[i+1][j+1]; // somma diagonale somma2 = a[i][j+1] + a[i+1][j]; // somma contro-diagonale if(somma1 == somma2) n_claque++; } } // Stampo prodotto printf("La matrice inserita ha %d Claque.\n", n_claque); return 0; } ``` --- # Somma Massima Sottomatrici Scrivere un programma che chiede all’utente di inserire una matrice di interi 20 × 30. Per ogni possibile dimensione B di sottomatrice quadrata, stampa un singolo intero che denota la somma massima di una sottomatrice di dimensione B x B. ```c #include <stdio.h> #define ROWS 20 #define COLS 30 int main(int argc, char* argv[]) { int matrix[ROWS][COLS]; int B, i, j, k, l, max_sum, current_sum, to_init=1; // Inserimento della matrice 20 x 30 printf("Inserisci la matrice 20 x 30 (600 numeri interi):\n"); for (i = 0; i < ROWS; i++) { for (j = 0; j < COLS; j++) { scanf("%d", &matrix[i][j]); } } // Ciclo per tutte le possibili dimensioni di sottomatrice B x B for (B = 1; B <= 20; B++) { max_sum = 0; to_init = 1; // Ciclo per trovare la sottomatrice con somma massima di dimensione B x B for (i = 0; i <= ROWS - B; i++) { for (j = 0; j <= COLS - B; j++) { current_sum = 0; // Calcola la somma della sottomatrice B x B con il vertice in (i, j) for (k = 0; k < B; k++) { for (l = 0; l < B; l++) { current_sum += matrix[i + k][j + l]; } } // Aggiorna la somma massima if (current_sum > max_sum || to_init) { max_sum = current_sum; to_init = 0; } } } // Stampa la somma massima per la dimensione B x B printf("Somma massima per sottomatrice %d x %d: %d\n", B, B, max_sum); } return 0; } ``` --- # Confronto Studenti con Matrici Modificare l’esercizio sul confronto studenti in modo tale da salvare ogni studente in una matrice di 3 righe. La prima riga della matrice ospita gli studenti di “AUT”, la seconda quelli di “INF”, la terza quella di “MAT”. Eliminare pertanto il campo sigla corso di iscrizione dalla struttura principale. Si svolgano tutti i punti dell’esercizio in questo nuovo contesto ```c #include <stdio.h> #include <string.h> #define N 5 #define LEN 100 int main(int argc, char* argv[]) { // Tipo typedef char stringa[LEN]; typedef struct { stringa nome; stringa cognome; int eta; float media; float ultimi_voti[3]; } Studente; // Variabili Studente studenti[3][N]; int i, eta_media_N, idx_max_media, j, flag, n_aut=0, n_inf=0, n_mat=0, corso, idx; float eta_media, max_media; // Acquisizione for(i=0; i<N; i++){ printf("Studente %d\n", i+1); do { printf("Che corso fa lo studente (0=AUT, 1=INF, 2=MAT)? "); scanf("%d", &corso); } while (corso < 0 || corso > 2); switch (corso) { case 0: n_aut++; idx = n_aut-1; break; case 1: n_inf++; idx = n_inf-1; break; case 2: n_mat++; idx = n_mat-1; break; default: idx = -1; break; } printf("Nome: "); scanf("%s", studenti[corso][idx].nome); fflush(stdin); printf("Cognome: "); scanf("%s", studenti[corso][idx].cognome); fflush(stdin); do { printf("Età: "); scanf("%d", &studenti[corso][idx].eta); } while(studenti[corso][idx].eta < 0); do { printf("Media: "); scanf("%f", &studenti[corso][idx].media); } while(studenti[corso][idx].media < 0 && studenti[corso][idx].media > 32); for (j=0; j<3; j++) { do { printf("Voto %d: ", j+1); scanf("%f", &studenti[corso][idx].ultimi_voti[j]); } while(studenti[corso][idx].ultimi_voti[j] < 0 && studenti[corso][idx].ultimi_voti[j] > 32); } } // Stampo età media di tutti printf("\nETA MEDIA\n"); eta_media = 0; for(i=0; i<n_aut; i++){ eta_media += studenti[0][i].eta; } for(i=0; i<n_inf; i++){ eta_media += studenti[1][i].eta; } for(i=0; i<n_mat; i++){ eta_media += studenti[2][i].eta; } eta_media /= N; printf("%.2f", eta_media); // Stampo età media degli studenti MAT printf("\nETA MEDIA MAT\n"); eta_media = 0; eta_media_N = 0; for(i=0; i<n_mat; i++){ eta_media += studenti[2][i].eta; } if(n_mat > 0){ eta_media /= n_mat; printf("%.2f", eta_media); } else{ printf("NO STUDENTI MAT\n"); } // Stampo nome e cognome dello studente INF con media più alta printf("\nSTUDENTE INF CON MEDIA PIù ALTA\n"); max_media = 0; idx_max_media = -1; for(i=0; i<n_inf; i++){ if(studenti[1][i].media > max_media){ max_media = studenti[1][i].media; idx_max_media = i; } } if(n_inf > 0) printf("%s - %s\n", studenti[1][idx_max_media].nome, studenti[1][idx_max_media].cognome); else printf("No studenti INF"); // Stampo nome e cognome degli studenti AUT con ultimi voti tutti >= 29 printf("\nSTUDENTE AUT CON ULTIMI VOTI SOPRA AL 29\n"); for(i=0; i<n_aut; i++){ flag = 0; for(j=0; j<3 && flag != 1; j++){ if(studenti[0][i].ultimi_voti[j] < 29) flag = 1; } if(!flag) printf("%s - %s\n", studenti[0][i].nome, studenti[0][i].cognome); } return 0; } ```