# Esercizi da TDE
## Liste - 08 Febbraio 2025
### Consegna
Si consideri un sistema che gestisce un insieme di playlist musicali. Ogni playlist è rappresentata da:
- Nome della playlist (stringa allocata dinamicamente);
- Una lista di canzoni appartenenti alla playlist.
Ogni canzone è rappresentata da:
- un titolo (stringa allocata dinamicamente);
- una durata in secondi (intero).
```clike=
// Struttura per rappresentare una canzone
typedef struct Canzone {
char *titolo; // Titolo della canzone (stringa dinamica)
int durata; // Durata in secondi
struct Canzone *next; // Puntatore alla prossima canzone
} Canzone;
// Struttura per rappresentare una playlist
typedef struct Playlist {
char *nome; // Nome della playlist (stringa dinamica)
Canzone *canzoni; // Lista di canzoni
struct Playlist *next; // Puntatore alla prossima playlist
} Playlist;
```
Si consideri di avere una lista di playlist musicali, opportunamente popolate.
- Si implementi una funzione “durataPlaylist” che, data una Playlist, calcola la durata totale della Playlist.
- Si implementi una funzione “riduciDurate” che prende in input una lista di Playlist e una durata massima.
La funzione verifica che ogni Playlist abbia una durata minore o uguale alla durata massima limite fornita. Se una Playlist non soddisfa questo requisito, la funzione elimina dalla Playlist il brano con durata minore finché la durata totale non soddisfa il vincolo. Tale controllo e tale eventuale modifica deve coinvolgere tutte le Playlist nella lista di Playlist.
- Si stampi nel main la lista delle Playlist prima e dopo l’applicazione della funzione “riduciDurate”.
Si supponga di avere accesso alla funzioni: “stampaTuttePlaylist” e “init” (che inizializza una playlist di partenza).
**Esempio (limite 600 secondi)** (p.s., generi volutamente invertiti):
Playlist prima della riduzione:
- Playlist: Pop
- Stairway to Heaven (480 secondi)
- Bohemian Rhapsody (355 secondi)
- Playlist: Rock
- Short Pop Song (90 secondi)
- Thriller (300 secondi)
Playlist dopo la riduzione:
- Playlist: Pop
- Stairway to Heaven (480 secondi)
- Playlist: Rock
- Short Pop Song (90 secondi)
- Thriller (300 secondi)
Viene dato il file di partenza:
```clike=
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Struttura per rappresentare una canzone
typedef struct Canzone {
char *titolo; // Titolo della canzone (stringa dinamica)
int durata; // Durata in secondi
struct Canzone *next; // Puntatore alla prossima canzone
} Canzone;
// Struttura per rappresentare una playlist
typedef struct Playlist {
char *nome; // Nome della playlist (stringa dinamica)
Canzone *canzoni; // Lista di canzoni
struct Playlist *next; // Puntatore alla prossima playlist
} Playlist;
// Prototipi
Playlist* init();
Playlist* creaPlaylist(Playlist *head, const char *nome);
void aggiungiCanzone(Playlist *playlist, const char *titolo, int durata);
void stampaTuttePlaylist(Playlist *head);
int main() {
// Creazione di playlist e canzoni
Playlist* playlists = init();
int durataMassima = 600;
// TODO
return 0;
}
// Crea playlist
Playlist * init(){
Playlist *playlists = NULL;
// Creazione delle playlist
playlists = creaPlaylist(playlists, "Rock");
playlists = creaPlaylist(playlists, "Pop");
// Aggiunta di canzoni alla playlist "Rock"
aggiungiCanzone(playlists, "Bohemian Rhapsody", 355);
aggiungiCanzone(playlists, "Stairway to Heaven", 480);
// Aggiunta di canzoni alla playlist "Pop"
aggiungiCanzone(playlists->next, "Thriller", 300);
aggiungiCanzone(playlists->next, "Short Pop Song", 90);
return playlists;
}
Playlist* creaPlaylist(Playlist *head, const char *nome) {
// Allocazione di una nuova playlist
Playlist *nuova = (Playlist *)malloc(sizeof(Playlist));
if (nuova == NULL) {
printf("Errore di allocazione memoria per la playlist");
return NULL;
}
// Allocazione dinamica per il nome della playlist
nuova->nome = (char *)malloc((strlen(nome) + 1) * sizeof(char));
if (nuova->nome == NULL) {
printf("Errore di allocazione memoria per il nome della playlist");
free(nuova);
return NULL;
}
// Copia del nome
strcpy(nuova->nome, nome);
// Inizializzazione della lista di canzoni
nuova->canzoni = NULL;
// Inserimento della nuova playlist in testa alla lista principale
nuova->next = head;
return nuova;
}
void aggiungiCanzone(Playlist *playlist, const char *titolo, int durata) {
if (playlist == NULL) {
printf("Errore: la playlist non esiste.\n");
return;
}
// Allocazione di una nuova canzone
Canzone *nuova = (Canzone *)malloc(sizeof(Canzone));
if (nuova == NULL) {
printf("Errore di allocazione memoria per la canzone");
return;
}
// Allocazione dinamica per il titolo della canzone
nuova->titolo = (char *)malloc((strlen(titolo) + 1) * sizeof(char));
if (nuova->titolo == NULL) {
printf("Errore di allocazione memoria per il titolo della canzone");
free(nuova);
return;
}
// Copia del titolo
strcpy(nuova->titolo, titolo);
// Assegnazione della durata
nuova->durata = durata;
// Inserimento della nuova canzone in testa alla lista delle canzoni della playlist
nuova->next = playlist->canzoni;
playlist->canzoni = nuova;
}
// Stampa
void stampaTuttePlaylist(Playlist *head) {
Playlist *curr = head;
while (curr != NULL) {
printf("Playlist: %s\n", curr->nome);
Canzone *canzone = curr->canzoni;
while (canzone != NULL) {
printf(" - %s (%d secondi)\n", canzone->titolo, canzone->durata);
canzone = canzone->next;
}
curr = curr->next;
printf("\n");
}
}
```
### Soluzione
```clike=
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Struttura per rappresentare una canzone
typedef struct Canzone {
char *titolo; // Titolo della canzone (stringa dinamica)
int durata; // Durata in secondi
struct Canzone *next; // Puntatore alla prossima canzone
} Canzone;
// Struttura per rappresentare una playlist
typedef struct Playlist {
char *nome; // Nome della playlist (stringa dinamica)
Canzone *canzoni; // Lista di canzoni
struct Playlist *next; // Puntatore alla prossima playlist
} Playlist;
// Prototipi
Playlist* init();
Playlist* creaPlaylist(Playlist *head, const char *nome);
void aggiungiCanzone(Playlist *playlist, const char *titolo, int durata);
int durataPlaylist(Playlist *playlist);
void eliminaCanzoneMinima(Playlist *playlist);
void riduciDurataPlaylist(Playlist *playlist, int durataMassima);
void riduciTutto(Playlist *head, int durataMassima);
void stampaTuttePlaylist(Playlist *head);
int main() {
// Creazione di playlist e canzoni
Playlist* playlists = init();
int durataMassima = 600;
// Stampa delle playlist
printf("Playlist iniziali:\n");
stampaTuttePlaylist(playlists);
// Stampa delle playlist prima della riduzione
printf("Playlist prima della riduzione:\n");
stampaTuttePlaylist(playlists);
// Applicazione della funzione riduciTutto
riduciTutto(playlists, durataMassima);
// Stampa delle playlist dopo la riduzione
printf("\nPlaylist dopo la riduzione:\n");
stampaTuttePlaylist(playlists);
return 0;
}
// Crea playlist
Playlist * init(){
Playlist *playlists = NULL;
// Creazione delle playlist
playlists = creaPlaylist(playlists, "Rock");
playlists = creaPlaylist(playlists, "Pop");
// Aggiunta di canzoni alla playlist "Rock"
aggiungiCanzone(playlists, "Bohemian Rhapsody", 355);
aggiungiCanzone(playlists, "Stairway to Heaven", 480);
// Aggiunta di canzoni alla playlist "Pop"
aggiungiCanzone(playlists->next, "Thriller", 300);
aggiungiCanzone(playlists->next, "Short Pop Song", 90);
return playlists;
}
Playlist* creaPlaylist(Playlist *head, const char *nome) {
// Allocazione di una nuova playlist
Playlist *nuova = (Playlist *)malloc(sizeof(Playlist));
if (nuova == NULL) {
printf("Errore di allocazione memoria per la playlist");
return NULL;
}
// Allocazione dinamica per il nome della playlist
nuova->nome = (char *)malloc((strlen(nome) + 1) * sizeof(char));
if (nuova->nome == NULL) {
printf("Errore di allocazione memoria per il nome della playlist");
free(nuova);
return NULL;
}
// Copia del nome
strcpy(nuova->nome, nome);
// Inizializzazione della lista di canzoni
nuova->canzoni = NULL;
// Inserimento della nuova playlist in testa alla lista principale
nuova->next = head;
return nuova;
}
void aggiungiCanzone(Playlist *playlist, const char *titolo, int durata) {
if (playlist == NULL) {
printf("Errore: la playlist non esiste.\n");
return;
}
// Allocazione di una nuova canzone
Canzone *nuova = (Canzone *)malloc(sizeof(Canzone));
if (nuova == NULL) {
printf("Errore di allocazione memoria per la canzone");
return;
}
// Allocazione dinamica per il titolo della canzone
nuova->titolo = (char *)malloc((strlen(titolo) + 1) * sizeof(char));
if (nuova->titolo == NULL) {
printf("Errore di allocazione memoria per il titolo della canzone");
free(nuova);
return;
}
// Copia del titolo
strcpy(nuova->titolo, titolo);
// Assegnazione della durata
nuova->durata = durata;
// Inserimento della nuova canzone in testa alla lista delle canzoni della playlist
nuova->next = playlist->canzoni;
playlist->canzoni = nuova;
}
// Durata
int durataPlaylist(Playlist *playlist) {
int totale = 0;
Canzone *curr = playlist->canzoni;
while (curr != NULL) {
totale += curr->durata;
curr = curr->next;
}
return totale;
}
// Elimina Canzone Minima
void eliminaCanzoneMinima(Playlist *playlist) {
if (playlist->canzoni == NULL) return;
Canzone *curr = playlist->canzoni;
Canzone *prec = NULL;
Canzone *min = curr;
Canzone *minPrec = NULL;
// Trova la canzone con durata minima
while (curr != NULL) {
if (curr->durata < min->durata) {
min = curr;
minPrec = prec;
}
prec = curr;
curr = curr->next;
}
// Elimina la canzone minima
if (minPrec == NULL) {
// La canzone minima è la prima
playlist->canzoni = min->next;
} else {
minPrec->next = min->next;
}
// Libera la memoria della canzone
free(min->titolo);
free(min);
}
// Riduci Durata
void riduciDurataPlaylist(Playlist *playlist, int durataMassima) {
while (durataPlaylist(playlist) > durataMassima) {
eliminaCanzoneMinima(playlist);
}
}
// Riduci la durata di tutte le playlist
void riduciTutto(Playlist *head, int durataMassima) {
Playlist *curr = head;
while (curr != NULL) {
riduciDurataPlaylist(curr, durataMassima);
curr = curr->next;
}
}
// Stampa
void stampaTuttePlaylist(Playlist *head) {
Playlist *curr = head;
while (curr != NULL) {
printf("Playlist: %s\n", curr->nome);
Canzone *canzone = curr->canzoni;
while (canzone != NULL) {
printf(" - %s (%d secondi)\n", canzone->titolo, canzone->durata);
canzone = canzone->next;
}
curr = curr->next;
printf("\n");
}
}
```
---
## Alberi Gennaio 2025
### Testo
Si scriva una funzione `check_tree()` che prenda in ingresso un albero di interi. La funzione deve ritornare
- 1 se la somma di tutti i nodi di profondità pari è uguale alla somma di tutti i nodi di profondità dispari.
- Altrimenti, la funzione deve ritornare 0
Per i seguenti alberi, dobbiamo ottenere 1 nel caso dell'albero di sinistra, 0 per l'albero di destra.

Alla fine del file di partenza sono riportati gli output che ci si aspetta.
Si parta dal seguente file:
```clike=
#include <stdio.h>
#include <stdlib.h>
typedef struct El {
int val;
struct El *left,*right;
} Nodo;
typedef Nodo *Albero;
Albero nN(int valore);
Albero costruisci1();
Albero costruisci2();
Albero costruisci3();
// TODO prototipi
int main() {
printf("Hello, World!\n");
Albero t1 = costruisci1();
Albero t2 = costruisci2();
Albero t3 = costruisci3();
// TODO invocare qui la funzione e stampare i risultati
return 0;
}
// Funzione per creare un nuovo nodo
Albero nN(int valore) {
Albero nodo = (Albero) malloc(sizeof(Nodo));
nodo->val = valore;
nodo->left = NULL;
nodo->right = NULL;
return nodo;
}
Albero costruisci1() {
Albero radice = nN(2);
radice->left = nN(1);
radice->right = nN(5);
radice->left->left = nN(0);
radice->left->right = nN(2);
radice->right->right = nN(2);
return radice;
}
Albero costruisci2() {
Albero radice = nN(5);
radice->left = nN(1);
radice->right = nN(5);
radice->left->left = nN(0);
radice->left->right = nN(2);
radice->right->right = nN(2);
return radice;
}
Albero costruisci3() {
Albero radice = nN(2);
radice->left = nN(5);
radice->left->left = nN(1);
radice->left->right = nN(2);
return radice;
}
// TODO implementare la funzione richiesta qui sotto
```
### Soluzione
```clike=
#include <stdio.h>
#include <stdlib.h>
typedef struct El {
int val;
struct El *left,*right;
} Nodo;
typedef Nodo *Albero;
Albero nN(int valore);
Albero costruisci1();
Albero costruisci2();
Albero costruisci3();
// TODO prototipi
int check_tree(Albero tree);
void sums(Albero tree, int *s_even, int *s_odd, int lvl);
int main() {
printf("Hello, World!\n");
Albero t1 = costruisci1();
Albero t2 = costruisci2();
Albero t3 = costruisci3();
// TODO invocare qui la funzione e stampare i risultati
printf("t1: %d\n", check_tree(t1));
printf("t1: %d\n", check_tree(t2));
printf("t1: %d\n", check_tree(t3));
return 0;
}
// Funzione per creare un nuovo nodo
Albero nN(int valore) {
Albero nodo = (Albero) malloc(sizeof(Nodo));
nodo->val = valore;
nodo->left = NULL;
nodo->right = NULL;
return nodo;
}
Albero costruisci1() {
Albero radice = nN(2);
radice->left = nN(1);
radice->right = nN(5);
radice->left->left = nN(0);
radice->left->right = nN(2);
radice->right->right = nN(2);
return radice;
}
Albero costruisci2() {
Albero radice = nN(5);
radice->left = nN(1);
radice->right = nN(5);
radice->left->left = nN(0);
radice->left->right = nN(2);
radice->right->right = nN(2);
return radice;
}
Albero costruisci3() {
Albero radice = nN(2);
radice->left = nN(5);
radice->left->left = nN(1);
radice->left->right = nN(2);
return radice;
}
// TODO implementare la funzione richiesta qui sotto
int check_tree(Albero tree) {
int sum_even=0, sum_odd = 0;
sums(tree, &sum_even, &sum_odd, 1);
return sum_even == sum_odd;
}
void sums(Albero tree, int *s_even, int *s_odd, int lvl) {
if(tree==NULL)
return;
if(lvl % 2 == 0)
*s_even += tree->val;
else
*s_odd += tree->val;
sums(tree->left, s_even, s_odd, lvl+1);
sums(tree->right, s_even, s_odd, lvl+1);
}
```
---
## Alberi Febbraio 2025
Questo esercizio presenta una leggera variazione rispetto al TDE originale
### Testo
Un albero si dice mediamente crescente se, per ogni suo nodo N, entrambe le medie dei due sottoalberi di N sono maggiori del valore del nodo N. La condizione si considera soddisfatta per la radice e le foglie.
Si scriva una funzione `checkTree()` che controlli se l’albero passato in ingresso è un albero mediamente crescente.
Si parta dal file:
```clike=
#include <stdio.h>
#include <stdlib.h>
// Struttura dell'albero binario
typedef struct ET {
int val;
struct ET *left, *right;
} treeNode;
typedef treeNode *tree;
// Funzioni
tree cn(int val);
void stampaAlbero(tree r, int spazio);
int checkTree(tree r);
tree costruisciAlbero1();
tree costruisciAlbero2();
tree costruisciAlbero3();
tree costruisciAlbero4();
int main() {
tree t1=costruisciAlbero1();
tree t2=costruisciAlbero2();
tree t3=costruisciAlbero3();
tree t4=costruisciAlbero4();
printf("Albero 1: %d\n", checkTree(t1));
printf("Albero 2: %d\n", checkTree(t2));
printf("Albero 3: %d\n", checkTree(t3));
printf("Albero 4: %d\n", checkTree(t4));
return 0;
}
int checkTree(tree r) {
//FUNZIONE DA SCRIVERE
return 0;
}
//AGGIUNGERE QUI FUNZIONI AUSILIARIE
tree cn(int val){
tree newNode=(tree)malloc(sizeof(treeNode));
newNode->val=val;
newNode->left=NULL;
newNode->right=NULL;
return newNode;
}
tree costruisciAlbero1(){
tree r=cn(1);
r->left=cn(5);
r->right=cn(7);
r->left->left=cn(21);
r->left->right=cn(38);
r->right->left=cn(12);
r->right->right=cn(24);
r->left->left->left=cn(100);
r->left->left->right=cn(83);
r->left->right->left=cn(67);
r->right->right->left=cn(91);
r->right->right->right=cn(75);
return r;
}
tree costruisciAlbero2(){
tree r=cn(8);
r->left=cn(4);
r->right=cn(2);
r->left->left=cn(6);
r->left->right=cn(11);
r->right->left=cn(10);
r->right->right=cn(14);
r->left->left->left=cn(18);
r->left->left->right=cn(30);
r->left->right->left=cn(54);
r->right->right->left=cn(72);
r->right->right->right=cn(75);
return r;
}
tree costruisciAlbero3(){
tree r=cn(10);
r->left=cn(5);
r->right=cn(15);
r->left->left=cn(1);
r->left->right=cn(7);
r->right->left=cn(12);
r->right->right=cn(20);
r->left->left->left=cn(0);
r->left->left->right=cn(2);
r->left->right->left=cn(6);
r->right->right->left=cn(18);
r->right->right->right=cn(5);
return r;
}
tree costruisciAlbero4(){
tree r=cn(9);
r->left=cn(4);
r->right=cn(14);
r->left->left=cn(1);
r->left->right=cn(6);
r->right->left=cn(10);
r->right->right=cn(18);
r->left->left->left=cn(0);
r->left->left->right=cn(2);
r->left->right->left=cn(5);
r->right->right->left=cn(17);
r->right->right->right=cn(30);
return r;
}
```
Eseguendo il codice sugli alberi creati nel file dato, l'output deve essere:
- Albero 1: 1
- Albero 2: 1
- Albero 3: 0
- Albero 4: 0
### Soluzione
```clike=
#include <stdio.h>
#include <stdlib.h>
// Struttura dell'albero binario
typedef struct ET {
int val;
struct ET *left, *right;
} treeNode;
typedef treeNode *tree;
// Funzioni
tree cn(int val);
void stampaAlbero(tree r, int spazio);
int checkTree(tree r);
tree costruisciAlbero1();
tree costruisciAlbero2();
tree costruisciAlbero3();
tree costruisciAlbero4();
// AGGIUNTE
float media(tree);
int conta_nodi(tree);
int somma_nodi(tree);
int main() {
tree t1=costruisciAlbero1();
tree t2=costruisciAlbero2();
tree t3=costruisciAlbero3();
tree t4=costruisciAlbero4();
printf("Albero 1: %d\n", checkTree(t1));
printf("Albero 2: %d\n", checkTree(t2));
printf("Albero 3: %d\n", checkTree(t3));
printf("Albero 4: %d\n", checkTree(t4));
return 0;
}
tree cn(int val){
tree newNode=(tree)malloc(sizeof(treeNode));
newNode->val=val;
newNode->left=NULL;
newNode->right=NULL;
return newNode;
}
tree costruisciAlbero1(){
tree r=cn(1);
r->left=cn(5);
r->right=cn(7);
r->left->left=cn(21);
r->left->right=cn(38);
r->right->left=cn(12);
r->right->right=cn(24);
r->left->left->left=cn(100);
r->left->left->right=cn(83);
r->left->right->left=cn(67);
r->right->right->left=cn(91);
r->right->right->right=cn(75);
return r;
}
tree costruisciAlbero2(){
tree r=cn(8);
r->left=cn(4);
r->right=cn(2);
r->left->left=cn(6);
r->left->right=cn(11);
r->right->left=cn(10);
r->right->right=cn(14);
r->left->left->left=cn(18);
r->left->left->right=cn(30);
r->left->right->left=cn(54);
r->right->right->left=cn(72);
r->right->right->right=cn(75);
return r;
}
tree costruisciAlbero3(){
tree r=cn(10);
r->left=cn(5);
r->right=cn(15);
r->left->left=cn(1);
r->left->right=cn(7);
r->right->left=cn(12);
r->right->right=cn(20);
r->left->left->left=cn(0);
r->left->left->right=cn(2);
r->left->right->left=cn(6);
r->right->right->left=cn(18);
r->right->right->right=cn(5);
return r;
}
tree costruisciAlbero4(){
tree r=cn(9);
r->left=cn(4);
r->right=cn(14);
r->left->left=cn(1);
r->left->right=cn(6);
r->right->left=cn(10);
r->right->right=cn(18);
r->left->left->left=cn(0);
r->left->left->right=cn(2);
r->left->right->left=cn(5);
r->right->right->left=cn(17);
r->right->right->right=cn(30);
return r;
}
int checkTree(tree r){
// Se l'albero è vuoto, la condizione è soddisfatta
if(r == NULL) return 1;
// NB! Controlliamo la media di un sottoalbero solo se esiste!
// E se la condizione non è soddisfatta ritorniamo subito false
if (r->left != NULL && media(r->left) < r->val)
return 0;
if (r->right != NULL && media(r->right) < r->val)
return 0;
// Arrivati qui, la condizione è soddisfatta per entrambi i sottoalberi, quindi controllo ricorsivamente che sia vera per entrambi i figli
// Per come è definito il caso base non serve controllare se i figli sono NULL!
return checkTree(r->left) && checkTree(r->right);
}
float media(tree r){
// Non viene mai chiamata su un albero NULL!! per come è implementata check_tree, ma è bene mettere un controllo comunque:
if (r == NULL) return 10e10; // Valore "impossibile" per non influenzare la media
return 1.0 * somma_nodi(r) / conta_nodi(r);
}
int conta_nodi(tree r){
if (r == NULL) return 0;
return 1 + conta_nodi(r->left) + conta_nodi(r->right);
}
int somma_nodi(tree r){
if (r == NULL) return 0;
return r->val + somma_nodi(r->left) + somma_nodi(r->right);
}
```
---
## Matrici Febbraio 2025
### Testo
Scrivere una funzione confronta che riceve due matrici M1 e M2 quadrate NxN di interi (ed eventuali altri parametri utili) e le scorre in parallelo confrontando le caselle in posizione corrispondente. La funzione deve riempire una terza matrice M3 sempre NxN mettendo in ogni casella 0 se i due elementi corrispondenti delle altre due matrici sono uguali, 1 se l'elemento di M1 è più grande, -1 se l'elemento di M2 è più grande. La funzione inoltre riporta al chiamante un vettore di dimensione N contenente la somma delle colonne di M3. M3 e il vettore devono essere riempiti nella funzione confronta e stampate nel main.
Alla fine del file di partenza sono riportati gli expected outputs.
Si parta dal seguente file:
```clike=
#include <stdio.h>
#include <stdlib.h>
#define N 4 // Dimensione della matrice NxN
int main() {
int M1[N][N] = {
{3, 5, 2, 8},
{6, 1, 4, 7},
{9, 2, 5, 3},
{4, 7, 6, 1}
};
int M2[N][N] = {
{3, 2, 2, 9},
{5, 1, 7, 6},
{8, 3, 5, 4},
{4, 8, 5, 0}
};
return 0;
}
```
Con le matrici date il risultato sarà:
Matrice M3 (risultato confronto):
```bash
0 1 0 -1
1 0 -1 1
1 -1 0 -1
0 -1 1 1
```
Somma delle colonne di M3:
```bash
2 -1 0 0
```
### Soluzione
```clike=
#include <stdio.h>
#include <stdlib.h>
#define N 4 // Dimensione della matrice NxN
void confronta(int M1[][N], int M2[][N], int M3[][N], int v[], int n);
int main() {
int M1[N][N] = {
{3, 5, 2, 8},
{6, 1, 4, 7},
{9, 2, 5, 3},
{4, 7, 6, 1}
};
int M2[N][N] = {
{3, 2, 2, 9},
{5, 1, 7, 6},
{8, 3, 5, 4},
{4, 8, 5, 0}
};
int M3[N][N]; // matrice risultato
int v[N]; // vettore risultato
confronta(M1, M2, M3, v, N);
// Stampa della matrice risultato
printf("Matrice risultato M3:\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%d ", M3[i][j]);
}
printf("\n");
}
// Stampa del vettore risultato
printf("Vettore risultato v:\n");
for (int j = 0; j < N; j++) {
printf("%d ", v[j]);
}
printf("\n");
return 0;
}
void confronta(int M1[][N], int M2[][N], int M3[][N], int v[], int n){
int i,j;
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(M1[i][j]==M2[i][j]){
M3[i][j]=0;
}
if(M1[i][j]>M2[i][j]){
M3[i][j]=1;
}
if(M1[i][j]<M2[i][j]){
M3[i][j]=-1;
}
}
}
for(j=0;j<n;j++){
v[j]=0; // meglio inizializzare qui ma non è un problema se si assume il vettore già inizializzato a zero nella funzione
for (i=0;i<n;i++){
v[j]+=M3[i][j];
}
}
}
```
---
## Matrici Gennaio 2025
### Testo
Si consideri un tipo di dato Tavolo composto da due campi interi che riportano il numero di persone sedute al tavolo e il prezzo totale del cibo ordinato dal tavolo:
```clike=
typedef struct {
int commensali; // Numero di persone sedute al tavolo
float prezzo; // Prezzo totale del cibo ordinato dal tavolo
} Tavolo;
```
La matrice quadrata M[N][N] rappresenta i tavoli di un ristorante, dove ciascun elemento contiene i dati relativi a un tavolo. Implementare le seguenti funzioni per analizzare e processare i dati della matrice.
- Si implementi una funzione “f1” che restituisce al chiamante i valori degli indici corrispondenti al tavolo con il minor numero di commensali che ha speso di più. La funzione prende in input la matrice rappresentante il ristorante (più eventuali campi aggiuntivi per la corretta gestione della matrice). Il chiamante deve stampare a schermo la posizione del tavolo in questione.
- Si implementi una funzione “f2” che prende in input la matrice rappresentante il ristorante (più eventuali campi aggiuntivi per la corretta gestione della matrice) e che “restituisce” un array che riporta il prezzo medio (in elementi diversi) speso dai tavoli aventi 2,3 e 4 commensali. Se nella matrice non è presente un tavolo con uno di quei numeri dei commensali, l’elemento corrispondente deve essere zero. Il chiamante deve stampare il risultato ottenuto.
- Si implementi infine una funzione “f3” che prende in input la matrice rappresentante il ristorante (più eventuali campi aggiuntivi per la corretta gestione della matrice) e che “restituisce” un array in cui ogni elemento è il prezzo massimo associato al tavolo su ogni diagonale parallela alla principale (diagonale principale esclusa) che si trovi al di sopra della diagonale principale stessa.
**Esempio**:
```clike
Tavolo M[3][3] = {
{{2, 100}, {3, 150}, {4, 200}},
{{2, 80}, {4, 180}, {3, 120}},
{{4, 250}, {2, 90}, {3, 140}}
};
```
- Indici del tavolo con meno commensali che ha speso di più: `(0, 0)`
- Prezzo medio per 2, 3, 4 commensali: `[90, 136.67, 210]`
- Prezzo massimo sulle diagonali parallele sopra la diagonale principale: `[150, 200]`
Si implementi il tutto a partire dal seguente codice:
```clike=
#include <stdio.h>
#define N 3
// Definizione del tipo Tavolo
typedef struct {
int commensali; // Numero di persone sedute al tavolo
float prezzo; // Prezzo totale del cibo ordinato dal tavolo
} Tavolo;
int main() {
// Matrice di tavoli
Tavolo M[N][N] = {
{{2, 100}, {3, 150}, {4, 200}},
{{2, 80}, {4, 180}, {3, 120}},
{{4, 250}, {2, 90}, {3, 140}}
};
// Chiamate alle funzioni
// Stampa dei risultati
return 0;
}
```
### Soluzione
```clike=
#include <stdio.h>
#define N 3
// Definizione del tipo Tavolo
typedef struct {
int commensali; // Numero di persone sedute al tavolo
int prezzo; // Prezzo totale del cibo ordinato dal tavolo
} Tavolo;
// Prototipi delle funzioni
void f1(Tavolo M[N][N], int n, int *riga, int *colonna);
void f2(Tavolo M[N][N], int n, float medie[3]);
void f3(Tavolo M[N][N], int n, int massimi[N - 1]);
int main() {
// Matrice di tavoli
Tavolo M[N][N] = {
{{2, 100}, {3, 150}, {4, 200}},
{{2, 80}, {4, 180}, {3, 120}},
{{4, 250}, {2, 90}, {3, 140}}
};
// Variabili per i risultati
int riga, colonna;
float medie[3] = {0}; // Prezzo medio per 2, 3, 4 commensali
int massimi[N - 1] = {0}; // Prezzo massimo per le diagonali parallele sopra la principale
// Chiamate alle funzioni
f1(M, N, &riga, &colonna);
f2(M, N, medie);
f3(M, N, massimi);
// Stampa dei risultati
printf("Tavolo con meno commensali che ha speso di più:\n");
printf("Indici: (%d, %d)\n", riga, colonna);
printf("Prezzo medio per 2, 3, 4 commensali:\n");
printf("[%.2f, %.2f, %.2f]\n", medie[0], medie[1], medie[2]);
printf("Prezzo massimo sulle diagonali parallele sopra la diagonale principale:\n");
printf("[");
for (int i = 0; i < N - 1; i++) {
printf("%d", massimi[i]);
if (i < N - 2) printf(", ");
}
printf("]\n");
return 0;
}
// Funzione f1
void f1(Tavolo M[N][N], int n, int *riga, int *colonna) {
int minCommensali = M[0][0].commensali;
int maxPrezzo = M[0][0].prezzo;
*riga = 0;
*colonna = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (M[i][j].commensali < minCommensali ||
(M[i][j].commensali == minCommensali && M[i][j].prezzo > maxPrezzo)) {
minCommensali = M[i][j].commensali;
maxPrezzo = M[i][j].prezzo;
*riga = i;
*colonna = j;
}
}
}
}
// Funzione f2
void f2(Tavolo M[N][N], int n, float medie[3]) {
int conteggio[3] = {0}; // Conteggio dei tavoli per 2, 3, 4 commensali
float somme[3] = {0}; // Somme dei prezzi per 2, 3, 4 commensali
// Calcolo delle somme e dei conteggi
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
switch (M[i][j].commensali) {
case 2: // Tavoli con 2 commensali
somme[0] += M[i][j].prezzo;
conteggio[0]++;
break;
case 3: // Tavoli con 3 commensali
somme[1] += M[i][j].prezzo;
conteggio[1]++;
break;
case 4: // Tavoli con 4 commensali
somme[2] += M[i][j].prezzo;
conteggio[2]++;
break;
default:
break; // Altri valori ignorati
}
}
}
// Calcolo delle medie
for (int i = 0; i < 3; i++) {
if (conteggio[i] > 0) {
medie[i] = somme[i] / conteggio[i]; // Media valida
} else {
medie[i] = 0; // Nessun tavolo con quel numero di commensali
}
}
}
// Funzione f3
void f3(Tavolo M[N][N], int n, int massimi[N - 1]) {
for (int offset = 1; offset < n; offset++) { // offset = distanza dalla diagonale principale
int massimo = 0;
for (int i = 0; i < n - offset; i++) {
int j = i + offset; // Indice colonna
if (M[i][j].prezzo > massimo) {
massimo = M[i][j].prezzo;
}
}
massimi[offset - 1] = massimo;
}
}
```