diff --git a/.gitignore b/.gitignore index cd531cf..06a9041 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,5 @@ Module.symvers Mkfile.old dkms.conf +# GDB history +.gdb_history diff --git a/Laboratorio 1/Esercizio 1/main.c b/Laboratorio 1/Esercizio 1/main.c new file mode 100644 index 0000000..d77fb97 --- /dev/null +++ b/Laboratorio 1/Esercizio 1/main.c @@ -0,0 +1,94 @@ +// Laboratorio 1 - Esercizio 1 +// Matteo Schiff - s295565 + +#include +#include +#include + +char *cercaRegexp(char *src, char *regexp); + +// NOTE: regexp has to be incremented after calling this function +bool checkChar(char src, char **regexp) +{ + switch (**regexp) + { + case '.': + return true; + case '[': + (*regexp)++; + int negate = **regexp == '^'; + + if (negate) + (*regexp)++; + + do + { + if (src == **regexp) { + while (**regexp != ']') + (*regexp)++; + return !negate; + } + (*regexp)++; + } while (**regexp != ']'); + + return negate; + case '\\': + (*regexp)++; + if (**regexp == 'a') { + return islower(src); + } else if (**regexp == 'A') { + return isupper(src); + } + return false; // NOTE: regex is not valid + default: + return src == **regexp; + } +} + +bool matchSubstring(char *src, char *regexp) +{ + char *cur_s = src; + char *cur_meta = regexp; + + while (*cur_meta != 0) + { + // match failed if regex check is false or if we reached the end + // of the string without reaching the end of the regex + if (*cur_s == 0 || !checkChar(*cur_s, &cur_meta)) + return false; + + cur_s++; + cur_meta++; + } + + return true; +} + +char *searchRegexp(char *src, char *regexp) +{ + char *cur_s = src; + + while (*cur_s != 0) + { + if (matchSubstring(cur_s, regexp)) + return cur_s; + cur_s++; + } + return 0; +} + +int main(int argc, char ** argv) { + if (argc != 3) { + puts("USAGE: ./esercizio1 string regexp"); + return 1; + } + + char * substr = searchRegexp(argv[1], argv[2]); + + if (!substr) { + puts("No matches"); + } else { + puts(substr); + } + return 0; +} diff --git a/Laboratorio 1/Esercizio 2/corse.txt b/Laboratorio 1/Esercizio 2/corse.txt new file mode 100644 index 0000000..60f96a2 --- /dev/null +++ b/Laboratorio 1/Esercizio 2/corse.txt @@ -0,0 +1,7 @@ +6 +GTT004 Marmolada Sebastopoli 2018/11/10 00:01:02 00:12:00 3 +GTT003 Einaudi Cso_Trapani 2018/09/10 14:11:23 14:38:23 2 +GTT002 Politecnico XVIII_Dicembre 2018/10/10 10:01:23 10:12:08 4 +GTT002 Politecnico Piazza_Statuto 2018/11/10 23:11:59 23:20:07 0 +GTT001 Braccini Porta_Nuova 2018/12/10 19:50:00 20:06:00 1 +GTT001 Braccini Porta_Nuova 2018/10/10 18:50:00 19:07:25 1 diff --git a/Laboratorio 1/Esercizio 2/main.c b/Laboratorio 1/Esercizio 2/main.c new file mode 100644 index 0000000..b61660c --- /dev/null +++ b/Laboratorio 1/Esercizio 2/main.c @@ -0,0 +1,249 @@ +// Laboratorio 1 - Esercizio 2 +// Matteo Schiff - s295565 + +#include +#include +#include +#include +#include +#define MAX_LEN 30 +#define MAX_ROWS 1000 + +const int MAXL = 50; + +typedef struct Time { + unsigned int hours; + unsigned int minutes; + unsigned int seconds; +} time; + +typedef struct Date { + unsigned int year; + unsigned int month; + unsigned int day; +} date; + +typedef struct Corsa { + char codice_tratta[MAX_LEN]; + char partenza[MAX_LEN]; + char destinazione[MAX_LEN]; + date data; + time ora_partenza; + time ora_arrivo; + unsigned int ritardo; +} corsa; + +typedef enum { + r_date, r_partenza, r_capolinea, r_ritardo, r_ritardo_tot, r_fine +} t_comandi; + +char* toLower(char* s); +t_comandi leggiComando(); +int confrontaDate(date a, date b); +void stampaCorsa(corsa corsa); +void data(char * argomenti, corsa corse[MAX_ROWS], int N); +void partenza(char * argomenti, corsa corse[MAX_ROWS], int N); +void capolinea(char * argomenti, corsa corse[MAX_ROWS], int N); +void ritardo(char * argomenti, corsa corse[MAX_ROWS], int N); +void ritardoTot(char * argomenti, corsa corse[MAX_ROWS], int N); +void menuParola (corsa corse[MAX_ROWS], int N); +int loadFile(corsa corse[MAX_ROWS], int * N, char * filename); + +// Trasforma in lowercase tutti i caratteri di una stringa +char* toLower(char* s) { + for(char *p=s; *p; p++) *p=tolower(*p); + return s; +} + +t_comandi leggiComando() { + t_comandi c; + char cmd[MAXL]; + char tabella[7][12] = { + "date", "partenza", "capolinea", "ritardo", "ritardo_tot", "fine" + }; + printf("comando (date/partenza/capolinea"); + printf("/ritardo/ritardo_tot/fine): "); + scanf("%s",cmd); toLower(cmd); + c=r_date; + while(c<7 && strcmp(cmd,tabella[c])!=0) + c++; + return (c); +} + +// restituisce true se la prima data è successiva o coincidente alla seconda +int confrontaDate(date a, date b) { + if (a.year > b.year) + return true; + else if (a.year < b.year) + return false; + + if (a.month > b.month) + return true; + else if (a.month < b.month) + return false; + + if (a.day >= b.day) + return true; + + return false; +} + +void stampaCorsa(corsa corsa) { + printf(" - %s %s %s, data: %4u/%02u/%02u, ora di partenza: %02u:%02u:%02u, ora di arrivo: %02u:%02u:%02u, ritardo %d minuto\n", + corsa.codice_tratta, corsa.partenza, corsa.destinazione, + corsa.data.year, corsa.data.month, corsa.data.day, + corsa.ora_partenza.hours, corsa.ora_partenza.minutes, corsa.ora_partenza.seconds, + corsa.ora_arrivo.hours, corsa.ora_arrivo.minutes, corsa.ora_arrivo.seconds, + corsa.ritardo); +} + +void data(char * argomenti, corsa corse[MAX_ROWS], int N) { + date data_inizio, data_fine; + if (sscanf(argomenti, " %4u/%2u/%2u %4u/%2u/%2u", &data_inizio.year, &data_inizio.month, &data_inizio.day, &data_fine.year, &data_fine.month, &data_fine.day) != 6) { + puts("Date non valide. La sintassi è 'date '"); + return; + } + + puts("Elenco corse con partenza compresa nell'intervallo specificato:\n"); + + for (int i = 0; i < N; i++) { + if (confrontaDate(corse[i].data, data_inizio) && confrontaDate(data_fine, corse[i].data)) { + stampaCorsa(corse[i]); + } + } +} + +void partenza(char * argomenti, corsa corse[MAX_ROWS], int N) { + char partenza[30]; + if (sscanf(argomenti, " %30s", partenza) != 1) { + puts("Partenza non valida. La sintassi è 'partenza '"); + return; + } + + printf("Elenco corse con partenza da %s:\n", partenza); + + for (int i = 0; i < N; i++) { + if (strcmp(partenza, corse[i].partenza) == 0) { + stampaCorsa(corse[i]); + } + } +} + +void capolinea(char * argomenti, corsa corse[MAX_ROWS], int N) { + char capolinea[30]; + if (sscanf(argomenti, " %30s", capolinea) != 1) { + puts("Capolinea non valido. La sintassi è 'capolinea '"); + return; + } + + printf("Elenco corse con capolinea da %s:\n", capolinea); + + for (int i = 0; i < N; i++) { + if (strcmp(capolinea, corse[i].destinazione) == 0) { + stampaCorsa(corse[i]); + } + } +} + +void ritardo(char * argomenti, corsa corse[MAX_ROWS], int N) { + date data_inizio, data_fine; + if (sscanf(argomenti, " %4u/%2u/%2u %4u/%2u/%2u", &data_inizio.year, &data_inizio.month, &data_inizio.day, &data_fine.year, &data_fine.month, &data_fine.day) != 6) { + puts("Date non valide. La sintassi è 'date '"); + return; + } + + puts("Eleco corse con ritardo nell'intervallo di date specificato:\n"); + + for (int i = 0; i < N; i++) { + if (confrontaDate(corse[i].data, data_inizio) && confrontaDate(data_fine, corse[i].data) && corse[i].ritardo > 0) { + stampaCorsa(corse[i]); + } + } +} + +void ritardoTot(char * argomenti, corsa corse[MAX_ROWS], int N) { + char codice_tratta[30]; + if (sscanf(argomenti, " %30s", codice_tratta) != 1) { + puts("Codice di tratta non valido. La sintassi è 'ritardo_tot '"); + return; + } + + unsigned int sum = 0; + + for (int i = 0; i < N; i++) { + if (strcmp(codice_tratta, corse[i].codice_tratta) == 0) { + sum += corse[i].ritardo; + } + } + + printf("Il ritardo complessivo accumulato sulla tratta %s è pari a %u minuti.\n", codice_tratta, sum); +} + +void menuParola (corsa corse[MAX_ROWS], int N) { + t_comandi comando; + char argomenti[MAXL]; + int i, continua=1; + while (continua) { + comando = leggiComando(); + fgets(argomenti,MAXL,stdin); /* resto della riga */ + switch (comando) { + case r_date: data(argomenti, corse, N); break; + case r_partenza: partenza(argomenti, corse, N); break; + case r_capolinea: capolinea(argomenti, corse, N); break; + case r_ritardo: ritardo(argomenti, corse, N); break; + case r_ritardo_tot: ritardoTot(argomenti, corse, N); break; + case r_fine: continua = 0; break; + default: + puts("Comando non valido\n"); + } + } +} + +int loadFile(corsa corse[MAX_ROWS], int * N, char * filename) { + FILE *fp_read; + unsigned int lines, i; + + if ((fp_read = fopen(filename, "r")) == NULL) + { + puts("Impossibile aprire il file"); + return 1; + } + + fscanf(fp_read, "%u\n", &lines); + + if (lines > MAX_ROWS) { + fclose(fp_read); + return 1; + } + + for (i = 0; i < lines; i++) { + int num_read = fscanf(fp_read, "%30s %30s %30s %4u/%2u/%2u %2u:%2u:%2u %2u:%2u:%2u %u\n", corse[i].codice_tratta, corse[i].partenza, corse[i].destinazione, &corse[i].data.year, &corse[i].data.month, &corse[i].data.day, &corse[i].ora_partenza.hours, &corse[i].ora_partenza.minutes, &corse[i].ora_partenza.seconds, &corse[i].ora_arrivo.hours, &corse[i].ora_arrivo.minutes, &corse[i].ora_arrivo.seconds, &corse[i].ritardo); + if (num_read != 13) { + // la stringa è mal formattata + printf("File non formattato correttamente. Errore a linea %d\n", i+1); + fclose(fp_read); + return 1; + } + } + + fclose(fp_read); + + *N = i; + return 0; +} + +int main() { + int N; + corsa corse[MAX_ROWS]; + + if (loadFile(corse, &N, "./corse.txt")) { + return 1; + } + + if (corse == NULL) { + return 1; + } + menuParola(corse, N); + + return 0; +} diff --git a/Laboratorio 1/Esercizio 3/corse.txt b/Laboratorio 1/Esercizio 3/corse.txt new file mode 100644 index 0000000..60f96a2 --- /dev/null +++ b/Laboratorio 1/Esercizio 3/corse.txt @@ -0,0 +1,7 @@ +6 +GTT004 Marmolada Sebastopoli 2018/11/10 00:01:02 00:12:00 3 +GTT003 Einaudi Cso_Trapani 2018/09/10 14:11:23 14:38:23 2 +GTT002 Politecnico XVIII_Dicembre 2018/10/10 10:01:23 10:12:08 4 +GTT002 Politecnico Piazza_Statuto 2018/11/10 23:11:59 23:20:07 0 +GTT001 Braccini Porta_Nuova 2018/12/10 19:50:00 20:06:00 1 +GTT001 Braccini Porta_Nuova 2018/10/10 18:50:00 19:07:25 1 diff --git a/Laboratorio 1/Esercizio 3/main.c b/Laboratorio 1/Esercizio 3/main.c new file mode 100644 index 0000000..0f9b4db --- /dev/null +++ b/Laboratorio 1/Esercizio 3/main.c @@ -0,0 +1,451 @@ +// Laboratorio 1 - Esercizio 3 +// Matteo Schiff - s295565 + +#include +#include +#include +#include +#include +#define MAX_LEN 30 +#define MAX_ROWS 1000 + +const int MAXL = 50; + +typedef struct Time +{ + unsigned int hours; + unsigned int minutes; + unsigned int seconds; +} time; + +typedef struct Date +{ + unsigned int year; + unsigned int month; + unsigned int day; +} date; + +typedef struct Corsa +{ + char codice_tratta[MAX_LEN]; + char partenza[MAX_LEN]; + char destinazione[MAX_LEN]; + date data; + time ora_partenza; + time ora_arrivo; + unsigned int ritardo; +} corsa; + +typedef enum +{ + k_codice_tratta, + k_partenza, + k_destinazione, + k_data +} corsa_keys; + +typedef enum +{ + r_stampa, + r_ordina_data, + r_ordina_codice, + r_ordina_partenza, + r_ordina_destinazione, + r_ricerca_partenza, + r_fine +} t_comandi; + +char *toLower(char *s); +t_comandi leggiComando(); +int confronta_data_ora(corsa *a, corsa *b); +void stampa_corsa(corsa corsa); +void stampa_corse(char *argomenti, corsa *corse[MAX_ROWS], int N); +void ordina_data(char *argomenti, corsa * corse[MAX_ROWS], int N); +void ordina_codice(char *argomenti, corsa * corse[MAX_ROWS], int N); +void ordina_partenza(char *argomenti, corsa * corse[MAX_ROWS], int N); +void ordina_arrivo(char *argomenti, corsa * corse[MAX_ROWS], int N); +void ricerca(char *argomenti, corsa * corse[MAX_ROWS], int N); +void menuParola(corsa * corse[MAX_ROWS], int N); +int loadFile(corsa corse[MAX_ROWS], int *N, char *filename); + +// Trasforma in lowercase tutti i caratteri di una stringa +char *toLower(char *s) +{ + for (char *p = s; *p; p++) + *p = tolower(*p); + return s; +} + +t_comandi leggiComando() +{ + t_comandi c; + char cmd[MAXL]; + char tabella[8][20] = { + "stampa", "ordina_data", "ordina_codice", "ordina_partenza", "ordina_destinazione", "ricerca", "fine"}; + printf("comando (stampa/ordina_data/ordina_codice"); + printf("/ordina_partenza/ordina_destinazione/ricerca/fine): "); + scanf("%s", cmd); + toLower(cmd); + c = r_stampa; + while (c < 8 && strcmp(cmd, tabella[c]) != 0) + c++; + return (c); +} + +corsa_keys interpreta_tratta(char *tratta) +{ + corsa_keys c; + char cmd[MAXL]; + char tabella[8][20] = { + "codice\n", "partenza\n", "destinazione\n", "data\n"}; + c = k_codice_tratta; + while (c < 8 && strcmp(tratta, tabella[c]) != 0) + c++; + return (c); +} + +// restituisce true se la prima data è successiva o coincidente alla seconda +int confronta_data_ora(corsa *a, corsa *b) +{ + if (a->data.year > b->data.year) + return true; + else if (a->data.year < b->data.year) + return false; + + if (a->data.month > b->data.month) + return true; + else if (a->data.month < b->data.month) + return false; + + if (a->data.day > b->data.day) + return true; + else if (a->data.day < b->data.day) + return false; + + if (a->ora_partenza.hours > b->ora_partenza.hours) + return true; + else if (a->ora_partenza.hours < b->ora_partenza.hours) + return false; + + if (a->ora_partenza.minutes > b->ora_partenza.minutes) + return true; + else if (a->ora_partenza.minutes < b->ora_partenza.minutes) + return false; + + if (a->ora_partenza.seconds >= b->ora_partenza.seconds) + return true; + + return false; +} + +int confronta_codice(corsa *a, corsa *b) +{ + return strcmp(a->codice_tratta, b->codice_tratta); +} + +int confronta_partenza(corsa *a, corsa *b) +{ + return strcmp(a->partenza, b->partenza) >= 0; +} + +int confronta_arrivo(corsa *a, corsa *b) +{ + return strcmp(a->destinazione, b->destinazione) >= 0; +} + +int confronta_chiave(corsa *a, corsa *b, corsa_keys chiave) +{ + switch (chiave) + { + case k_codice_tratta: + return confronta_codice(a, b); + case k_destinazione: + return confronta_arrivo(a, b); + case k_partenza: + return confronta_partenza(a, b); + case k_data: + return confronta_data_ora(a, b); + } +} + +int min(int x, int y) +{ + return (x < y) ? x : y; +} + +void merge(corsa *A[MAX_ROWS], int low, int mid, int high, corsa_keys chiave) +{ + int i, j, k; + // Merge the temp arrays + corsa * temp[MAX_ROWS]; + i = low; + j = mid+1; + k = 0; + while (i <= mid && j <= high) + { + if (!confronta_chiave(A[i], A[j], chiave)) + { + temp[k] = A[i]; + i++; + } + else + { + temp[k] = A[j]; + j++; + } + k++; + } + // Copy the remaining elements of L[] + while (i <= mid) + { + temp[k] = A[i]; + i++; + k++; + } + // Copy the remaining elements of R[] + while (j <= high) + { + temp[k] = A[j]; + j++; + k++; + } + + for (i = 0; i <= high - low; i++) { + A[i+low] = temp[i]; + } +} + +void mergesort_by_key(corsa *A[MAX_ROWS], int low, int high, corsa_keys key) +{ + if (low >= high) + return; + + // Finding mid element + int mid = low + (high - low) / 2; + // Recursively sorting both the halves + mergesort_by_key(A, low, mid, key); + mergesort_by_key(A, mid + 1, high, key); + + // Merge the array + merge(A, low, mid, high, key); +} + +void stampa_corsa(corsa corsa) +{ + printf(" - %s %s %s, data: %4u/%02u/%02u, ora di partenza: %02u:%02u:%02u, ora di arrivo: %02u:%02u:%02u, ritardo %d minuto\n", + corsa.codice_tratta, corsa.partenza, corsa.destinazione, + corsa.data.year, corsa.data.month, corsa.data.day, + corsa.ora_partenza.hours, corsa.ora_partenza.minutes, corsa.ora_partenza.seconds, + corsa.ora_arrivo.hours, corsa.ora_arrivo.minutes, corsa.ora_arrivo.seconds, + corsa.ritardo); +} + +void stampa_corse(char *argomenti, corsa * corse[MAX_ROWS], int N) +{ + puts("Elenco delle corse:"); + for (int i = 0; i < N; i++) + { + stampa_corsa(*(corse[i])); + } +} + +void ordina_data(char *argomenti, corsa * corse[MAX_ROWS], int N) +{ + puts("Ordino le corse per data\n"); + + mergesort_by_key(corse, 0, N - 1, k_data); +} + +void ordina_codice(char *argomenti, corsa * corse[MAX_ROWS], int N) +{ + puts("Ordino le corse per codice tratta\n"); + + mergesort_by_key(corse, 0, N - 1, k_codice_tratta); +} + +void ordina_partenza(char *argomenti, corsa * corse[MAX_ROWS], int N) +{ + puts("Ordino le corse per partenza\n"); + + mergesort_by_key(corse, 0, N - 1, k_partenza); +} + +void ordina_arrivo(char *argomenti, corsa * corse[MAX_ROWS], int N) +{ + puts("Ordino le corse per destinazione\n"); + + mergesort_by_key(corse, 0, N - 1, k_destinazione); +} + +void ricerca_dicotomica(corsa *corse[MAX_ROWS], char *partenza, int partenza_len, int N) +{ + int s = 0, e = N - 1, i = (e + s) / 2, res = strncmp(partenza, corse[i]->partenza, partenza_len); + while (res != 0) + { + if (e-s <= 0) { //nothing found + puts("Nessun risultato"); + return; + } + + if (res > 0) + { + s = i+1; + } + else + { + e = i-1; + } + i = (e + s) / 2; + res = strncmp(partenza, corse[i]->partenza, partenza_len); + } + + s = i; + e = i; + while (s > 0 && !strncmp(partenza, corse[s - 1]->partenza, partenza_len)) + s--; + + while (e < (N - 1) && !strncmp(partenza, corse[e + 1]->partenza, partenza_len)) + e++; + + for (i = s; i <= e; i++) + { + stampa_corsa(*(corse[i])); + } +} + +void ricerca_lineare(corsa *corse[MAX_ROWS], char *partenza, int partenza_len, int N) +{ + for (int i = 0; i < N; i++) { + if (!strncmp(partenza, corse[i]->partenza, partenza_len)) + stampa_corsa(*(corse[i])); + } +} + +void ricerca_partenza(char *argomenti, corsa * corse[MAX_ROWS], int N) +{ + char partenza[30], tipo[30], partenza_len; + if (sscanf(argomenti, " %30s %30s", tipo, partenza) != 2) + { + puts("Partenza non valida. La sintassi è 'partenza [dicotomica/lineare] '"); + return; + } + + partenza_len = strlen(partenza); + + puts("Risultati della ricerca per stazione di partenza:"); + + if (!strcmp(tipo, "dicotomica")) + { + ricerca_dicotomica(corse, partenza, partenza_len, N); + } + else + { + ricerca_lineare(corse, partenza, partenza_len, N); + } +} + +void menuParola(corsa * corse[MAX_ROWS], int N) +{ + t_comandi comando; + char argomenti[MAXL]; + int i, continua = 1; + while (continua) + { + comando = leggiComando(); + fgets(argomenti, MAXL, stdin); /* resto della riga */ + switch (comando) + { + case r_stampa: + stampa_corse(argomenti, corse, N); + break; + case r_ordina_data: + ordina_data(argomenti, corse, N); + break; + case r_ordina_codice: + ordina_codice(argomenti, corse, N); + break; + case r_ordina_destinazione: + ordina_arrivo(argomenti, corse, N); + break; + case r_ordina_partenza: + ordina_partenza(argomenti, corse, N); + break; + case r_ricerca_partenza: + ricerca_partenza(argomenti, corse, N); + break; + case r_fine: + continua = 0; + break; + default: + puts("Comando non valido\n"); + } + } +} + +void fillArray(corsa corse[MAX_ROWS], corsa *corse_ptr[MAX_ROWS], int N) +{ + for (int i = 0; i < N; i++) + { + corse_ptr[i] = &corse[i]; + } +} + +int loadFile(corsa corse[MAX_ROWS], int *N, char *filename) +{ + FILE *fp_read; + unsigned int lines, i; + + if ((fp_read = fopen(filename, "r")) == NULL) + { + puts("Impossibile aprire il file"); + return 1; + } + + fscanf(fp_read, "%u\n", &lines); + + if (lines > MAX_ROWS) + { + fclose(fp_read); + return 1; + } + + for (i = 0; i < lines; i++) + { + int num_read = fscanf(fp_read, "%30s %30s %30s %4u/%2u/%2u %2u:%2u:%2u %2u:%2u:%2u %u\n", corse[i].codice_tratta, corse[i].partenza, corse[i].destinazione, &corse[i].data.year, &corse[i].data.month, &corse[i].data.day, &corse[i].ora_partenza.hours, &corse[i].ora_partenza.minutes, &corse[i].ora_partenza.seconds, &corse[i].ora_arrivo.hours, &corse[i].ora_arrivo.minutes, &corse[i].ora_arrivo.seconds, &corse[i].ritardo); + if (num_read != 13) + { + // la stringa è mal formattata + printf("File non formattato correttamente. Errore a linea %d\n", i + 1); + fclose(fp_read); + return 1; + } + } + + fclose(fp_read); + + *N = i; + return 0; +} + +int main() +{ + int N; + corsa corse[MAX_ROWS]; + corsa * corse_ptr[MAX_ROWS]; + + if (loadFile(corse, &N, "./corse.txt")) + { + return 1; + } + + if (corse == NULL) + { + return 1; + } + + fillArray(corse, corse_ptr, N); + + menuParola(corse_ptr, N); + + return 0; +} diff --git a/Laboratorio 1/Esercizio 4/corse.txt b/Laboratorio 1/Esercizio 4/corse.txt new file mode 100644 index 0000000..60f96a2 --- /dev/null +++ b/Laboratorio 1/Esercizio 4/corse.txt @@ -0,0 +1,7 @@ +6 +GTT004 Marmolada Sebastopoli 2018/11/10 00:01:02 00:12:00 3 +GTT003 Einaudi Cso_Trapani 2018/09/10 14:11:23 14:38:23 2 +GTT002 Politecnico XVIII_Dicembre 2018/10/10 10:01:23 10:12:08 4 +GTT002 Politecnico Piazza_Statuto 2018/11/10 23:11:59 23:20:07 0 +GTT001 Braccini Porta_Nuova 2018/12/10 19:50:00 20:06:00 1 +GTT001 Braccini Porta_Nuova 2018/10/10 18:50:00 19:07:25 1 diff --git a/Laboratorio 1/Esercizio 4/main.c b/Laboratorio 1/Esercizio 4/main.c new file mode 100644 index 0000000..dd0d079 --- /dev/null +++ b/Laboratorio 1/Esercizio 4/main.c @@ -0,0 +1,476 @@ +// Laboratorio 1 - Esercizio 4 +// Matteo Schiff - s295565 + +#include +#include +#include +#include +#include +#define MAX_LEN 30 +#define MAX_ROWS 1000 + +const int MAXL = 50; + +typedef struct Time +{ + unsigned int hours; + unsigned int minutes; + unsigned int seconds; +} time; + +typedef struct Date +{ + unsigned int year; + unsigned int month; + unsigned int day; +} date; + +typedef struct Corsa +{ + char codice_tratta[MAX_LEN]; + char partenza[MAX_LEN]; + char destinazione[MAX_LEN]; + date data; + time ora_partenza; + time ora_arrivo; + unsigned int ritardo; +} corsa; + +typedef struct Raccolta +{ + corsa *corse_data[MAX_ROWS]; + corsa *corse_codice[MAX_ROWS]; + corsa *corse_partenza[MAX_ROWS]; + corsa *corse_arrivo[MAX_ROWS]; +} raccolta; + +typedef enum +{ + k_codice_tratta, + k_partenza, + k_destinazione, + k_data +} corsa_keys; + +typedef enum +{ + r_stampa, + r_ordina_data, + r_ordina_codice, + r_ordina_partenza, + r_ordina_destinazione, + r_ricerca_partenza, + r_fine +} t_comandi; + +// Trasforma in lowercase tutti i caratteri di una stringa +char *toLower(char *s) +{ + for (char *p = s; *p; p++) + *p = tolower(*p); + return s; +} + +t_comandi leggiComando() +{ + t_comandi c; + char cmd[MAXL]; + char tabella[8][20] = { + "stampa", "ordina_data", "ordina_codice", "ordina_partenza", "ordina_destinazione", "ricerca", "fine"}; + printf("comando (stampa/ordina_data/ordina_codice"); + printf("/ordina_partenza/ordina_destinazione/ricerca/fine): "); + scanf("%s", cmd); + toLower(cmd); + c = r_stampa; + while (c < 8 && strcmp(cmd, tabella[c]) != 0) + c++; + return (c); +} + +corsa_keys interpreta_tratta(char *tratta) +{ + corsa_keys c; + char cmd[MAXL]; + char tabella[8][20] = { + "codice\n", "partenza\n", "destinazione\n", "data\n"}; + c = k_codice_tratta; + while (c < 8 && strcmp(tratta, tabella[c]) != 0) + c++; + return (c); +} + +// restituisce true se la prima data è successiva o coincidente alla seconda +int confronta_data_ora(corsa *a, corsa *b) +{ + if (a->data.year > b->data.year) + return true; + else if (a->data.year < b->data.year) + return false; + + if (a->data.month > b->data.month) + return true; + else if (a->data.month < b->data.month) + return false; + + if (a->data.day > b->data.day) + return true; + else if (a->data.day < b->data.day) + return false; + + if (a->ora_partenza.hours > b->ora_partenza.hours) + return true; + else if (a->ora_partenza.hours < b->ora_partenza.hours) + return false; + + if (a->ora_partenza.minutes > b->ora_partenza.minutes) + return true; + else if (a->ora_partenza.minutes < b->ora_partenza.minutes) + return false; + + if (a->ora_partenza.seconds >= b->ora_partenza.seconds) + return true; + + return false; +} + +int confronta_codice(corsa *a, corsa *b) +{ + return strcmp(a->codice_tratta, b->codice_tratta); +} + +int confronta_partenza(corsa *a, corsa *b) +{ + return strcmp(a->partenza, b->partenza) >= 0; +} + +int confronta_arrivo(corsa *a, corsa *b) +{ + return strcmp(a->destinazione, b->destinazione) >= 0; +} + +int confronta_chiave(corsa *a, corsa *b, corsa_keys chiave) +{ + switch (chiave) + { + case k_codice_tratta: + return confronta_codice(a, b); + case k_destinazione: + return confronta_arrivo(a, b); + case k_partenza: + return confronta_partenza(a, b); + case k_data: + return confronta_data_ora(a, b); + } +} + +int min(int x, int y) +{ + return (x < y) ? x : y; +} + +void merge(corsa *A[MAX_ROWS], int low, int mid, int high, corsa_keys chiave) +{ + int i, j, k; + corsa * temp[MAX_ROWS]; + // Merge the temp arrays + i = low; + j = mid+1; + k = 0; + while (i <= mid && j <= high) + { + if (!confronta_chiave(A[i], A[j], chiave)) + { + temp[k] = A[i]; + i++; + } + else + { + temp[k] = A[j]; + j++; + } + k++; + } + // Copy the remaining elements of L[] + while (i <= mid) + { + temp[k] = A[i]; + i++; + k++; + } + // Copy the remaining elements of R[] + while (j <= high) + { + temp[k] = A[j]; + j++; + k++; + } + + for (i = 0; i <= high - low; i++) { + A[i+low] = temp[i]; + } +} + +void mergesort_by_key(corsa *A[MAX_ROWS], int low, int high, corsa_keys key) +{ + if (low >= high) + return; + + // Finding mid element + int mid = low + (high - low) / 2; + // Recursively sorting both the halves + mergesort_by_key(A, low, mid, key); + mergesort_by_key(A, mid + 1, high, key); + + // Merge the array + merge(A, low, mid, high, key); +} + +void stampa_corsa(corsa corsa) +{ + printf(" - %s %s %s, data: %4u/%02u/%02u, ora di partenza: %02u:%02u:%02u, ora di arrivo: %02u:%02u:%02u, ritardo %d minuto\n", + corsa.codice_tratta, corsa.partenza, corsa.destinazione, + corsa.data.year, corsa.data.month, corsa.data.day, + corsa.ora_partenza.hours, corsa.ora_partenza.minutes, corsa.ora_partenza.seconds, + corsa.ora_arrivo.hours, corsa.ora_arrivo.minutes, corsa.ora_arrivo.seconds, + corsa.ritardo); +} + +void stampa_corse_vettore(corsa **corse, int N) +{ + for (int i = 0; i < N; i++) + { + stampa_corsa(*(corse[i])); + } +} + +void stampa_corse_scelta(char *argomenti, raccolta *rac, int N) +{ + argomenti++; // salta lo spazio + switch (interpreta_tratta(argomenti)) + { + case k_codice_tratta: + puts("Corse ordinate per codice:"); + stampa_corse_vettore(rac->corse_codice, N); + break; + case k_data: + puts("Corse ordinate per data:"); + stampa_corse_vettore(rac->corse_data, N); + break; + case k_destinazione: + puts("Corse ordinate per destinazione:"); + stampa_corse_vettore(rac->corse_arrivo, N); + break; + case k_partenza: + puts("Corse ordinate per partenza:"); + stampa_corse_vettore(rac->corse_partenza, N); + break; + + default: + puts("Errore. La sintassi è 'stampa [codice/partenza/destinazione/data]'"); + break; + } +} + +void ordina_data(char *argomenti, raccolta *rac, int N) +{ + puts("Ordino le corse per data\n"); + + mergesort_by_key(rac->corse_data, 0, N - 1, k_data); +} + +void ordina_codice(char *argomenti, raccolta *rac, int N) +{ + puts("Ordino le corse per codice tratta\n"); + + mergesort_by_key(rac->corse_codice, 0, N - 1, k_codice_tratta); +} + +void ordina_partenza(char *argomenti, raccolta *rac, int N) +{ + puts("Ordino le corse per partenza\n"); + + mergesort_by_key(rac->corse_partenza, 0, N - 1, k_partenza); +} + +void ordina_arrivo(char *argomenti, raccolta *rac, int N) +{ + puts("Ordino le corse per destinazione\n"); + + mergesort_by_key(rac->corse_arrivo, 0, N - 1, k_destinazione); +} + +void ricerca_dicotomica(corsa *corse[MAX_ROWS], char *partenza, int partenza_len, int N) +{ + int s = 0, e = N - 1, i = (e + s) / 2, res = strncmp(partenza, corse[i]->partenza, partenza_len); + while (res != 0) + { + if (e-s <= 0) { //nothing found + puts("Nessun risultato"); + return; + } + + if (res > 0) + { + s = i+1; + } + else + { + e = i-1; + } + i = (e + s) / 2; + res = strncmp(partenza, corse[i]->partenza, partenza_len); + } + + s = i; + e = i; + while (s > 0 && !strncmp(partenza, corse[s - 1]->partenza, partenza_len)) + s--; + + while (e < (N - 1) && !strncmp(partenza, corse[e + 1]->partenza, partenza_len)) + e++; + + for (i = s; i <= e; i++) + { + stampa_corsa(*(corse[i])); + } +} + +void ricerca_lineare(corsa *corse[MAX_ROWS], char *partenza, int partenza_len, int N) +{ + for (int i = 0; i < N; i++) { + if (!strncmp(partenza, corse[i]->partenza, partenza_len)) + stampa_corsa(*(corse[i])); + } +} + +void ricerca_partenza(char *argomenti, raccolta *rac, int N) +{ + char partenza[30], tipo[30], partenza_len; + if (sscanf(argomenti, " %30s %30s", tipo, partenza) != 2) + { + puts("Partenza non valida. La sintassi è 'partenza [dicotomica/lineare] '"); + return; + } + + partenza_len = strlen(partenza); + + puts("Risultati della ricerca per stazione di partenza:"); + + if (!strcmp(tipo, "dicotomica")) + { + ricerca_dicotomica(rac->corse_partenza, partenza, partenza_len, N); + } + else + { + ricerca_lineare(rac->corse_partenza, partenza, partenza_len, N); + } +} + +void menuParola(raccolta *rac, int N) +{ + t_comandi comando; + char argomenti[MAXL]; + int i, continua = 1; + while (continua) + { + comando = leggiComando(); + fgets(argomenti, MAXL, stdin); /* resto della riga */ + switch (comando) + { + case r_stampa: + stampa_corse_scelta(argomenti, rac, N); + break; + case r_ordina_data: + ordina_data(argomenti, rac, N); + break; + case r_ordina_codice: + ordina_codice(argomenti, rac, N); + break; + case r_ordina_destinazione: + ordina_arrivo(argomenti, rac, N); + break; + case r_ordina_partenza: + ordina_partenza(argomenti, rac, N); + break; + case r_ricerca_partenza: + ricerca_partenza(argomenti, rac, N); + break; + case r_fine: + continua = 0; + break; + default: + puts("Comando non valido\n"); + } + } +} + +void fillArray(corsa corse[MAX_ROWS], corsa *corse_ptr[MAX_ROWS], int N) +{ + for (int i = 0; i < N; i++) + { + corse_ptr[i] = &corse[i]; + } +} + +int loadFile(corsa corse[MAX_ROWS], int *N, char *filename) +{ + FILE *fp_read; + unsigned int lines, i; + + if ((fp_read = fopen(filename, "r")) == NULL) + { + puts("Impossibile aprire il file"); + return 1; + } + + fscanf(fp_read, "%u\n", &lines); + + if (lines > MAX_ROWS) + { + fclose(fp_read); + return 1; + } + + for (i = 0; i < lines; i++) + { + int num_read = fscanf(fp_read, "%30s %30s %30s %4u/%2u/%2u %2u:%2u:%2u %2u:%2u:%2u %u\n", corse[i].codice_tratta, corse[i].partenza, corse[i].destinazione, &corse[i].data.year, &corse[i].data.month, &corse[i].data.day, &corse[i].ora_partenza.hours, &corse[i].ora_partenza.minutes, &corse[i].ora_partenza.seconds, &corse[i].ora_arrivo.hours, &corse[i].ora_arrivo.minutes, &corse[i].ora_arrivo.seconds, &corse[i].ritardo); + if (num_read != 13) + { + // la stringa è mal formattata + printf("File non formattato correttamente. Errore a linea %d\n", i + 1); + fclose(fp_read); + return 1; + } + } + + fclose(fp_read); + + *N = i; + return 0; +} + +int main() +{ + int N; + corsa corse[MAX_ROWS]; + raccolta rac; + + if (loadFile(corse, &N, "./corse.txt")) + { + return 1; + } + + if (corse == NULL) + { + return 1; + } + + fillArray(corse, rac.corse_data, N); + fillArray(corse, rac.corse_codice, N); + fillArray(corse, rac.corse_partenza, N); + fillArray(corse, rac.corse_arrivo, N); + + menuParola(&rac, N); + + return 0; +} diff --git a/Laboratorio 2/Esercizio 1/main.c b/Laboratorio 2/Esercizio 1/main.c new file mode 100644 index 0000000..aed0ffc --- /dev/null +++ b/Laboratorio 2/Esercizio 1/main.c @@ -0,0 +1,45 @@ +// Laboratorio 2 - Esercizio 1 +// Matteo Schiff - s295565 + +#include +#include + +int gcd(int a, int b) { + if (b > a) { // inverti in modo che a > b + int c = a; + a = b; + b = c; + } + + if (a == b) + return a; + + if (b == 1) + return 1; + + if (b % 2 == 0) { + if (a % 2 == 0) { + return 2*gcd(a/2,b/2); + } else { + return gcd(a, b/2); + } + } else if (a % 2 == 0) { + // il caso `a` pari, `b` dispari + // non è presente nel testo + return gcd(a/2,b); + } + + return gcd((a-b)/2, b); +} + +int main(int argc, char ** argv) { + int a, b; + + if (argc != 3) + return 1; + + a = atoi(argv[1]); + b = atoi(argv[2]); + + printf("gcd: %i\n", gcd(a, b)); +} \ No newline at end of file diff --git a/Laboratorio 2/Esercizio 2/main.c b/Laboratorio 2/Esercizio 2/main.c new file mode 100644 index 0000000..1bbfa0e --- /dev/null +++ b/Laboratorio 2/Esercizio 2/main.c @@ -0,0 +1,89 @@ +// Laboratorio 2 - Esercizio 2 +// Matteo Schiff - s295565 + +#include +#include + +int ** matrmalloc(int * nc, int * nr) { + FILE *fp_read; + + if ((fp_read = fopen("mat.txt", "r")) == NULL) + { + puts("Impossibile aprire il file"); + return NULL; + } + + fscanf(fp_read, "%u %u\n", nr, nc); + + int ** mat = malloc(*nr * sizeof(int *)); + + for (int i = 0; i < *nr; i++) { + int * row = malloc(*nc * sizeof(int)); + for (int j = 0; j < *nc; j++) { + fscanf(fp_read, "%d ", &row[j]); + } + mat[i] = row; + } + + fclose(fp_read); + return mat; +} + +void matrfree(int **mat, int nr) { + for (int i = 0; i < nr; i++) { + free(mat[i]); + } + + free(mat); +} + +void separa(int **mat, int nr, int nc, int ** bianchi, int ** neri, int * nbianchi, int * nneri) { + int a = nc % 2; + int x = nc / 2; + int b = nr % 2; + int y = nr / 2; + + *nneri = (x + a) * y + x * (y + b); + *nbianchi = x * y + (x+a) * (y + b); + + *bianchi = malloc(*nbianchi * sizeof(int)); + *neri = malloc(*nneri * sizeof(int)); + + int conta_bianchi = 0, conta_neri = 0; + + for (int i = 0; i < nr; i++) { + for (int j = 0; j < nc; j++) { + if ((i+j) % 2 == 0) { + (*bianchi)[conta_bianchi++] = mat[i][j]; + } else { + (*neri)[conta_neri++] = mat[i][j]; + } + } + } +} + +int main(int argc, char ** argv) { + int nc, nr; + int ** mat = matrmalloc(&nc, &nr); + + if (mat == NULL) { + return 1; + } + + int *bianchi, *neri, n_bianchi, n_neri; + separa(mat, nr, nc, &bianchi, &neri, &n_bianchi, &n_neri); + + puts("Numeri su caselle bianche:"); + for (int i = 0; i < n_bianchi; i++) + printf("%u\n", bianchi[i]); + + puts("Numeri su caselle nere:"); + for (int i = 0; i < n_neri; i++) + printf("%u\n", neri[i]); + + matrfree(mat, nr); + free(bianchi); + free(neri); + + return 0; +} \ No newline at end of file diff --git a/Laboratorio 2/Esercizio 2/mat.txt b/Laboratorio 2/Esercizio 2/mat.txt new file mode 100644 index 0000000..63eb41e --- /dev/null +++ b/Laboratorio 2/Esercizio 2/mat.txt @@ -0,0 +1,4 @@ +3 3 +1 2 3 +4 5 6 +7 8 9 \ No newline at end of file diff --git a/Laboratorio 2/Esercizio 3/corse.txt b/Laboratorio 2/Esercizio 3/corse.txt new file mode 100644 index 0000000..39c1808 --- /dev/null +++ b/Laboratorio 2/Esercizio 3/corse.txt @@ -0,0 +1,8 @@ +6 +GTT004 Marmolada Sebastopoli 2018/11/10 00:01:02 00:12:00 3 +GTT003 Einaudi Cso_Trapani 2018/09/10 14:11:23 14:38:23 2 +GTT002 Politecnico XVIII_Dicembre 2018/10/10 10:01:23 10:12:08 4 +GTT002 Politecnico Piazza_Statuto 2018/11/10 23:11:59 23:20:07 0 +GTT001 Braccini Porta_Nuova 2018/12/10 19:50:00 20:06:00 1 +GTT001 Braccini Porta_Nuova 2018/10/10 18:50:00 19:07:25 1 + diff --git a/Laboratorio 2/Esercizio 3/corse2.txt b/Laboratorio 2/Esercizio 3/corse2.txt new file mode 100644 index 0000000..077c885 --- /dev/null +++ b/Laboratorio 2/Esercizio 3/corse2.txt @@ -0,0 +1,8 @@ +6 +GTT004 SantOttavio Sebastopoli 2018/11/10 00:01:02 00:12:00 3 +GTT003 Vinzaglio Cso_Trapani 2018/09/10 14:11:23 14:38:23 2 +GTT002 Politecnico XVIII_Dicembre 2018/10/10 10:01:23 10:12:08 4 +GTT002 Politecnico Piazza_Statuto 2018/11/10 23:11:59 23:20:07 0 +GTT001 XVIII_Dicembre Porta_Nuova 2018/12/10 19:50:00 20:06:00 1 +GTT001 Braccini Porta_Nuova 2018/10/10 18:50:00 19:07:25 1 + diff --git a/Laboratorio 2/Esercizio 3/main.c b/Laboratorio 2/Esercizio 3/main.c new file mode 100644 index 0000000..1342640 --- /dev/null +++ b/Laboratorio 2/Esercizio 3/main.c @@ -0,0 +1,496 @@ +// Laboratorio 2 - Esercizio 3 +// Matteo Schiff - s295565 + +#include +#include +#include +#include +#include +#define MAX_LEN 30 + +const int MAXL = 50; + +typedef struct Time +{ + unsigned int hours; + unsigned int minutes; + unsigned int seconds; +} time; + +typedef struct Date +{ + unsigned int year; + unsigned int month; + unsigned int day; +} date; + +typedef struct Corsa +{ + char codice_tratta[MAX_LEN]; + char partenza[MAX_LEN]; + char destinazione[MAX_LEN]; + date data; + time ora_partenza; + time ora_arrivo; + unsigned int ritardo; +} corsa; + +typedef struct Raccolta +{ + int N; + corsa **corse_data; + corsa **corse_codice; + corsa **corse_partenza; + corsa **corse_arrivo; + corsa **temp; +} raccolta; + +typedef enum +{ + k_codice_tratta, + k_partenza, + k_destinazione, + k_data +} corsa_keys; + +typedef enum +{ + r_stampa, + r_ordina_data, + r_ordina_codice, + r_ordina_partenza, + r_ordina_destinazione, + r_ricerca_partenza, + r_carica, + r_fine +} t_comandi; + +// Trasforma in lowercase tutti i caratteri di una stringa +char *toLower(char *s) +{ + for (char *p = s; *p; p++) + *p = tolower(*p); + return s; +} + +t_comandi leggiComando() +{ + t_comandi c; + char cmd[MAXL]; + char tabella[9][20] = { + "stampa", "ordina_data", "ordina_codice", "ordina_partenza", "ordina_destinazione", "ricerca", "carica", "fine"}; + printf("comando (stampa/ordina_data/ordina_codice"); + printf("/ordina_partenza/ordina_destinazione/ricerca/carica/fine): "); + scanf("%s", cmd); + toLower(cmd); + c = r_stampa; + while (c < 9 && strcmp(cmd, tabella[c]) != 0) + c++; + return (c); +} + +corsa_keys interpreta_tratta(char *tratta) +{ + corsa_keys c; + char cmd[MAXL]; + char tabella[8][20] = { + "codice\n", "partenza\n", "destinazione\n", "data\n"}; + c = k_codice_tratta; + while (c < 8 && strcmp(tratta, tabella[c]) != 0) + c++; + return (c); +} + +// restituisce true se la prima data è successiva o coincidente alla seconda +int confronta_data_ora(corsa *a, corsa *b) +{ + if (a->data.year > b->data.year) + return true; + else if (a->data.year < b->data.year) + return false; + + if (a->data.month > b->data.month) + return true; + else if (a->data.month < b->data.month) + return false; + + if (a->data.day > b->data.day) + return true; + else if (a->data.day < b->data.day) + return false; + + if (a->ora_partenza.hours > b->ora_partenza.hours) + return true; + else if (a->ora_partenza.hours < b->ora_partenza.hours) + return false; + + if (a->ora_partenza.minutes > b->ora_partenza.minutes) + return true; + else if (a->ora_partenza.minutes < b->ora_partenza.minutes) + return false; + + if (a->ora_partenza.seconds >= b->ora_partenza.seconds) + return true; + + return false; +} + +int confronta_codice(corsa *a, corsa *b) +{ + return strcmp(a->codice_tratta, b->codice_tratta); +} + +int confronta_partenza(corsa *a, corsa *b) +{ + return strcmp(a->partenza, b->partenza) >= 0; +} + +int confronta_arrivo(corsa *a, corsa *b) +{ + return strcmp(a->destinazione, b->destinazione) >= 0; +} + +int confronta_chiave(corsa *a, corsa *b, corsa_keys chiave) +{ + switch (chiave) + { + case k_codice_tratta: + return confronta_codice(a, b); + case k_destinazione: + return confronta_arrivo(a, b); + case k_partenza: + return confronta_partenza(a, b); + case k_data: + return confronta_data_ora(a, b); + } +} + +int freeVettori(raccolta * rac) { + for (int i = 0; i < rac->N; i++) + { + free(rac->corse_codice[i]); + } + + free(rac->corse_data); + free(rac->corse_partenza); + free(rac->corse_arrivo); + free(rac->corse_codice); + free(rac->temp); +} + +int loadFile(raccolta * rac, char *filename, int callFree) +{ + FILE *fp_read; + unsigned int i; + + if ((fp_read = fopen(filename, "r")) == NULL) + { + puts("Impossibile aprire il file"); + return 1; + } + + if (callFree) { + // chiamo free solo dopo aver controllato che il file esista + // se il file non esiste rimangono caricati i dati precedenti + freeVettori(rac); + } + + fscanf(fp_read, "%u\n", &(rac->N)); + + rac->corse_data = malloc(rac->N * sizeof(corsa *)); + rac->corse_partenza = malloc(rac->N * sizeof(corsa *)); + rac->corse_arrivo = malloc(rac->N * sizeof(corsa *)); + rac->corse_codice = malloc(rac->N * sizeof(corsa *)); + rac->temp = malloc(rac->N * sizeof(corsa *)); + + for (i = 0; i < rac->N; i++) + { + corsa * nuova = malloc(sizeof(corsa)); + int num_read = fscanf(fp_read, "%30s %30s %30s %4u/%2u/%2u %2u:%2u:%2u %2u:%2u:%2u %u\n", nuova->codice_tratta, nuova->partenza, nuova->destinazione, &(nuova->data.year), &(nuova->data.month), &(nuova->data.day), &(nuova->ora_partenza.hours), &(nuova->ora_partenza.minutes), &(nuova->ora_partenza.seconds), &(nuova->ora_arrivo.hours), &(nuova->ora_arrivo.minutes), &(nuova->ora_arrivo.seconds), &(nuova->ritardo)); + if (num_read != 13) + { + // la stringa è mal formattata + printf("File non formattato correttamente. Errore a linea %d\n", i + 1); + fclose(fp_read); + return 1; + } + rac->corse_data[i] = nuova; + rac->corse_partenza[i] = nuova; + rac->corse_arrivo[i] = nuova; + rac->corse_codice[i] = nuova; + } + + fclose(fp_read); + return 0; +} + +int min(int x, int y) +{ + return (x < y) ? x : y; +} + +void merge(corsa **A, corsa ** temp, int low, int mid, int high, corsa_keys chiave) +{ + int i, j, k; + // Merge the temp arrays + i = low; + j = mid+1; + k = 0; + while (i <= mid && j <= high) + { + if (!confronta_chiave(A[i], A[j], chiave)) + { + temp[k] = A[i]; + i++; + } + else + { + temp[k] = A[j]; + j++; + } + k++; + } + // Copy the remaining elements of L[] + while (i <= mid) + { + temp[k] = A[i]; + i++; + k++; + } + // Copy the remaining elements of R[] + while (j <= high) + { + temp[k] = A[j]; + j++; + k++; + } + + for (i = 0; i <= high - low; i++) { + A[i+low] = temp[i]; + } +} + +void mergesort_by_key(corsa **A, corsa ** temp, int low, int high, corsa_keys key) +{ + if (low >= high) + return; + + // Finding mid element + int mid = low + (high - low) / 2; + // Recursively sorting both the halves + mergesort_by_key(A, temp, low, mid, key); + mergesort_by_key(A, temp, mid + 1, high, key); + + // Merge the array + merge(A, temp, low, mid, high, key); +} + +void stampa_corsa(corsa corsa) +{ + printf(" - %s %s %s, data: %4u/%02u/%02u, ora di partenza: %02u:%02u:%02u, ora di arrivo: %02u:%02u:%02u, ritardo %d minuto\n", + corsa.codice_tratta, corsa.partenza, corsa.destinazione, + corsa.data.year, corsa.data.month, corsa.data.day, + corsa.ora_partenza.hours, corsa.ora_partenza.minutes, corsa.ora_partenza.seconds, + corsa.ora_arrivo.hours, corsa.ora_arrivo.minutes, corsa.ora_arrivo.seconds, + corsa.ritardo); +} + +void stampa_corse_vettore(corsa **corse, int N) +{ + for (int i = 0; i < N; i++) + { + stampa_corsa(*(corse[i])); + } +} + +void stampa_corse_scelta(char *argomenti, raccolta * rac) +{ + argomenti++; // salta lo spazio + switch (interpreta_tratta(argomenti)) + { + case k_codice_tratta: + puts("Corse ordinate per codice:"); + stampa_corse_vettore(rac->corse_codice, rac->N); + break; + case k_data: + puts("Corse ordinate per data:"); + stampa_corse_vettore(rac->corse_data, rac->N); + break; + case k_destinazione: + puts("Corse ordinate per destinazione:"); + stampa_corse_vettore(rac->corse_arrivo, rac->N); + break; + case k_partenza: + puts("Corse ordinate per partenza:"); + stampa_corse_vettore(rac->corse_partenza, rac->N); + break; + + default: + puts("Errore. La sintassi è 'stampa [codice/partenza/destinazione/data]'"); + break; + } +} + +void ordina_data(char *argomenti, raccolta * rac) +{ + puts("Ordino le corse per data\n"); + + mergesort_by_key(rac->corse_data, rac->temp, 0, rac->N - 1, k_data); +} + +void ordina_codice(char *argomenti, raccolta * rac) +{ + puts("Ordino le corse per codice tratta\n"); + + mergesort_by_key(rac->corse_codice, rac->temp, 0, rac->N - 1, k_codice_tratta); +} + +void ordina_partenza(char *argomenti, raccolta * rac) +{ + puts("Ordino le corse per partenza\n"); + + mergesort_by_key(rac->corse_partenza, rac->temp, 0, rac->N - 1, k_partenza); +} + +void ordina_arrivo(char *argomenti, raccolta * rac) +{ + puts("Ordino le corse per destinazione\n"); + + mergesort_by_key(rac->corse_arrivo, rac->temp, 0, rac->N - 1, k_destinazione); +} + +void ricerca_dicotomica(corsa **corse, char *partenza, int partenza_len, int N) +{ + int s = 0, e = N - 1, i = (e + s) / 2, res = strncmp(partenza, corse[i]->partenza, partenza_len); + while (res != 0) + { + if (e-s <= 0) { //nothing found + puts("Nessun risultato"); + return; + } + + if (res > 0) + { + s = i+1; + } + else + { + e = i-1; + } + i = (e + s) / 2; + res = strncmp(partenza, corse[i]->partenza, partenza_len); + } + + s = i; + e = i; + while (s > 0 && !strncmp(partenza, corse[s - 1]->partenza, partenza_len)) + s--; + + while (e < (N - 1) && !strncmp(partenza, corse[e + 1]->partenza, partenza_len)) + e++; + + for (i = s; i <= e; i++) + { + stampa_corsa(*(corse[i])); + } +} + +void ricerca_lineare(corsa **corse, char *partenza, int partenza_len, int N) +{ + for (int i = 0; i < N; i++) { + if (!strncmp(partenza, corse[i]->partenza, partenza_len)) + stampa_corsa(*(corse[i])); + } +} + +void ricerca_partenza(char *argomenti, raccolta * rac) +{ + char partenza[30], tipo[30], partenza_len; + if (sscanf(argomenti, " %30s %30s", tipo, partenza) != 2) + { + puts("Partenza non valida. La sintassi è 'partenza [dicotomica/lineare] '"); + return; + } + + partenza_len = strlen(partenza); + + puts("Risultati della ricerca per stazione di partenza:"); + + if (!strcmp(tipo, "dicotomica")) + { + ricerca_dicotomica(rac->corse_partenza, partenza, partenza_len, rac->N); + } + else + { + ricerca_lineare(rac->corse_partenza, partenza, partenza_len, rac->N); + } +} + +void carica_file(char *argomenti, raccolta * rac) +{ + char filename[30], partenza_len; + if (sscanf(argomenti, " %30s", filename) != 1) + { + puts("Sintassi non valida. La sintassi è 'carica '"); + return; + } + + puts("Carico il nuovo file..."); + loadFile(rac, filename, true); +} + +void menuParola(raccolta * rac) +{ + t_comandi comando; + char argomenti[MAXL]; + int i, continua = 1; + while (continua) + { + comando = leggiComando(); + fgets(argomenti, MAXL, stdin); /* resto della riga */ + switch (comando) + { + case r_stampa: + stampa_corse_scelta(argomenti, rac); + break; + case r_ordina_data: + ordina_data(argomenti, rac); + break; + case r_ordina_codice: + ordina_codice(argomenti, rac); + break; + case r_ordina_destinazione: + ordina_arrivo(argomenti, rac); + break; + case r_ordina_partenza: + ordina_partenza(argomenti, rac); + break; + case r_ricerca_partenza: + ricerca_partenza(argomenti, rac); + break; + case r_carica: + carica_file(argomenti, rac); + break; + case r_fine: + continua = 0; + break; + default: + puts("Comando non valido\n"); + } + } +} + +int main() +{ + raccolta rac; + + if (loadFile(&rac, "./corse.txt", false)) + { + return 1; + } + + menuParola(&rac); + freeVettori(&rac); + + return 0; +} diff --git a/Laboratorio 3/Esercizio 1/main.c b/Laboratorio 3/Esercizio 1/main.c new file mode 100644 index 0000000..a202e0e --- /dev/null +++ b/Laboratorio 3/Esercizio 1/main.c @@ -0,0 +1,56 @@ +// Laboratorio 3 - Esercizio 1 +// Matteo Schiff - s295565 + +#include +#include + +int majority(int * a, int N) { + if (N == 1) { + return a[0]; + } + + int m = N/2; + + int x = majority(a, m); + int y = majority(a+m, m); + + if (x == y) + return x; + + if (x != -1) { + int c = 0; + for (int i = 0; i < N; i++) { + if (a[i] == x) + c++; + } + if (c > (N/2)) + return x; + } + + if (y != -1) { + int c = 0; + for (int i = 0; i < N; i++) { + if (a[i] == y) + c++; + } + + if (c > (N/2)) + return y; + } + + return -1; +} + +int main(int argc, char ** argv) { + int N = argc - 1; + + if (argc < 2) + return 1; + + int * vec = malloc(N * sizeof(int)); + for (int i = 0; i < N; i++) { + vec[i] = atoi(argv[i+1]); + } + + printf("major: %d\n", majority(vec, N)); +} diff --git a/Laboratorio 3/Esercizio 2/brani.txt b/Laboratorio 3/Esercizio 2/brani.txt new file mode 100644 index 0000000..59e8af0 --- /dev/null +++ b/Laboratorio 3/Esercizio 2/brani.txt @@ -0,0 +1,26 @@ +5 + 5 + DivideAndConquer + MementoMori + LegacyOfHate_Pt.III + GhostLoveScore + TheHowling + 3 + BirdSetFree + ThePrayer + SomeoneLikeYou + 4 + Yellow + Wonderwall + MessageInABottle + FreeBird + 5 + GliAngeli + HoMessoVia + GliAnni + ReginaDiCuori + Pescatore + 3 + ISeeFire + ChasingCars + HowToSaveALife diff --git a/Laboratorio 3/Esercizio 2/main.c b/Laboratorio 3/Esercizio 2/main.c new file mode 100644 index 0000000..4281236 --- /dev/null +++ b/Laboratorio 3/Esercizio 2/main.c @@ -0,0 +1,87 @@ +// Laboratorio 3 - Esercizio 2 +// Matteo Schiff - s295565 + +#include +#include +#define MAX_LEN 255 + +typedef struct Lista +{ + unsigned int N; + char *canzoni; +} lista; + +lista *leggi_brani(int *N, int **playlist) +{ + FILE *fp_read; + + if ((fp_read = fopen("brani.txt", "r")) == NULL) + { + puts("Impossibile aprire il file"); + return NULL; + } + + fscanf(fp_read, "%u \n", N); + + lista *raccolta = malloc(*N * sizeof(lista)); + *playlist = malloc(*N * sizeof(int)); + + for (int i = 0; i < *N; i++) + { + fscanf(fp_read, "%u \n", &(raccolta[i].N)); + raccolta[i].canzoni = malloc(raccolta[i].N * MAX_LEN * sizeof(char)); + for (int j = 0; j < raccolta[i].N; j++) + { + fscanf(fp_read, "%s ", raccolta[i].canzoni + j * MAX_LEN); + } + } + + fclose(fp_read); + return raccolta; +} + +void free_brani(lista *mat, int N, int *playlist) +{ + for (int i = 0; i < N; i++) + { + free(mat[i].canzoni); + } + + free(mat); + free(playlist); +} + +void stampa_playlist(lista *mat, int *playlist, int N, int depth) +{ + if (N == depth) + { + puts("\nPlaylist:"); + for (int i = 0; i < N; i++) + { + printf(" - %s\n", (mat[i].canzoni + playlist[i] * MAX_LEN)); + } + return; + } + + for (int i = 0; i < mat[depth].N; i++) + { + playlist[depth] = i; + stampa_playlist(mat, playlist, N, depth + 1); + } +} + +int main(int argc, char **argv) +{ + int N; + int *playlist; + lista *mat = leggi_brani(&N, &playlist); + + if (mat == NULL) + { + return 1; + } + + stampa_playlist(mat, playlist, N, 0); + free_brani(mat, N, playlist); + return 0; +} diff --git a/Laboratorio 4/Esercizio 1/grafo.txt b/Laboratorio 4/Esercizio 1/grafo.txt new file mode 100644 index 0000000..3de991e --- /dev/null +++ b/Laboratorio 4/Esercizio 1/grafo.txt @@ -0,0 +1,5 @@ +4 4 +0 1 +0 2 +1 2 +1 3 diff --git a/Laboratorio 4/Esercizio 1/main.c b/Laboratorio 4/Esercizio 1/main.c new file mode 100644 index 0000000..0d9fdc2 --- /dev/null +++ b/Laboratorio 4/Esercizio 1/main.c @@ -0,0 +1,77 @@ +// Laboratorio 4 - Esercizio 1 +// Matteo Schiff - s295565 + +#include +#include +#define FILENAME "grafo.txt" + +int checkVertexCover(int *soluzione, int N, int **archi, int E) { + for (int i = 0; i < E; i++) { + if (soluzione[archi[i][0]] == 0 && soluzione[archi[i][1]] == 0) + return 0; + } + return 1; +} + +void vertexCoverR(int pos, int **archi, int E, int *soluzione, int N) { + if (pos >= N) { + if (checkVertexCover(soluzione, N, archi, E)) { + printf("("); + for (int i = 0; i < N; i++) { + if (soluzione[i] == 1) { + printf("%d,", i); + } + } + printf("\b)\n"); + } + return; + } + + soluzione[pos] = 0; + vertexCoverR(pos+1, archi, E, soluzione, N); + soluzione[pos] = 1; + vertexCoverR(pos+1, archi, E, soluzione, N); +} + +void vertexCovers(int **archi, int N, int E) { + int *soluzione = (int *) malloc(N * sizeof(int)); + vertexCoverR(0, archi, E, soluzione, N); + free(soluzione); +} + +void leggiGrafo(int ***archi, int *N, int *E) { + FILE *fp; + + if ((fp = fopen(FILENAME, "r")) == NULL) { + printf("Impossibile aprire il file di input %s", FILENAME); + exit(1); + } + + fscanf(fp, "%d %d", N, E); + *archi = (int **) malloc(*E * sizeof(int *)); + if (*archi == NULL) { + printf("Impossibile allocare memoria"); + exit(2); + } + + for (int i = 0; i < *E; i++) { + (*archi)[i] = (int *) malloc(2 * sizeof(int)); + if ((*archi)[i] == NULL) { + printf("Impossibile allocare memoria"); + exit(2); + } + fscanf(fp, "%d %d", &(*archi)[i][0], &(*archi)[i][1]); + } + fclose(fp); +} + +int main(int argc, char ** argv) +{ + int **archi, N, E; + + leggiGrafo(&archi, &N, &E); + vertexCovers(archi, N, E); + free(archi); + + return 0; +} diff --git a/Laboratorio 4/Esercizio 2/anag1.txt b/Laboratorio 4/Esercizio 2/anag1.txt new file mode 100644 index 0000000..60ec40a --- /dev/null +++ b/Laboratorio 4/Esercizio 2/anag1.txt @@ -0,0 +1,3 @@ +A0001 Mario Rossi 01/02/1990 ViaMarcoPolo Torino 10129 +A0002 Lucia Verdi 07/11/1989 ViaTorino Milano 20123 +A0003 Antonio Neri 19/04/1999 GalleriaTermini Roma 00185 \ No newline at end of file diff --git a/Laboratorio 4/Esercizio 2/anag2.txt b/Laboratorio 4/Esercizio 2/anag2.txt new file mode 100644 index 0000000..fc77843 --- /dev/null +++ b/Laboratorio 4/Esercizio 2/anag2.txt @@ -0,0 +1,2 @@ +A0004 Anna Gialli 04/09/1995 FratelliAlinari Firenze 50123 +A0005 Marco Bianchi 03/07/1993 PiazzaMazzini Napoli 80135 \ No newline at end of file diff --git a/Laboratorio 4/Esercizio 2/item.c b/Laboratorio 4/Esercizio 2/item.c new file mode 100644 index 0000000..1f40486 --- /dev/null +++ b/Laboratorio 4/Esercizio 2/item.c @@ -0,0 +1,192 @@ +// Laboratorio 4 - Esercizio 2 - item.c +// Matteo Schiff - s295565 + +#ifndef ITEM_C_DEFINED +#define ITEM_C_DEFINED + +#include +#include +#include +#include +#include "item.h" + +int DateGreater(Date a, Date b) { + if (a.year > b.year) + return true; + else if (a.year < b.year) + return false; + + if (a.month > b.month) + return true; + else if (a.month < b.month) + return false; + + if (a.day >= b.day) + return true; + + return false; +} + +Link newNode(Item val, Link next) { + Link t = (Link) malloc(sizeof(Node)); + if (t == NULL) { + printf("Impossibile allocare memoria"); + exit(2); + } + t->val = val; + t->next = next; + + return t; +} + +void freeNode(Link node) { + free(node->val); + free(node); +} + +Item ItemFromString(char *str) { + Item item; + + if ((item = (Item) malloc(sizeof(struct item_s))) == NULL) { + printf("Impossibile allocare memoria"); + exit(2); + } + + if (sscanf(str, " %5s %50s %50s %d/%d/%d %50s %50s %d", + item->code, + item->name, + item->surname, + &item->date.day, + &item->date.month, + &item->date.year, + item->address, + item->city, + &item->cap + ) != 9) { + free(item); + return NULL; + } + + return item; +} + +Item ItemRead(FILE * fp) { + Item item; + + if ((item = (Item) malloc(sizeof(struct item_s))) == NULL) { + printf("Impossibile allocare memoria"); + exit(2); + } + + if (fscanf(fp, " %5s %50s %50s %d/%d/%d %50s %50s %d", + item->code, + item->name, + item->surname, + &item->date.day, + &item->date.month, + &item->date.year, + item->address, + item->city, + &item->cap + ) != 9) { + free(item); + return NULL; + } + + return item; +} + +Key ItemKey(Item val) { + return val->code; +} + +int ItemEq(Key x, Key y) { + return strcmp(x, y) == 0; +} + +void ItemPrint(FILE *fp, Item x) { + fprintf(fp, "%s %s %s %02d/%02d/%04d %s %s %05d\n", + x->code, + x->name, + x->surname, + x->date.day, + x->date.month, + x->date.year, + x->address, + x->city, + x->cap + ); +} + +Link insertOrderedByDate(Item val, Link head) { + Link x, p; + + if (head == NULL || DateGreater(val->date, head->val->date)) + return newNode(val, head); + + for (p = head, x = head->next; x != NULL && DateGreater(x->val->date, val->date); p = x, x = x->next); + p->next = newNode(val, x); + + return head; +} + +Item getItemByCode(Link head, Key key) { + for (Link t = head; t != NULL; t = t->next) { + if (ItemEq(ItemKey(t->val), key)) + return t->val; + } + + return NULL; +} + +void printList(FILE *fp, Link head) { + for (Link t = head; t != NULL; t = t->next) { + ItemPrint(fp, t->val); + } +} + +Item extractCode(Link *headp, Key key) { + Link *t, r; + Item element = NULL; + + for (t = headp; *t != NULL; t = &((*t)->next)) { + if (ItemEq(ItemKey((*t)->val), key)) { + element = (*t)->val; + // Salvo `r` per poi chiamare free + r = *t; + // rimuovo il nodo dalla lista + *t = (*t)->next; + // Faccio free solo del nodo (non dell'item) + free(r); + break; + } + } + + return element; +} + +Item extractDates(Link *headp, Date first, Date last) { + Link *t, r; + Item element = NULL; + + for (t = headp; *t != NULL; t = &((*t)->next)) { + if (DateGreater((*t)->val->date, first) && DateGreater(last, (*t)->val->date)) { + element = (*t)->val; + r = *t; + *t = (*t)->next; + free(r); + break; + } + } + + return element; +} + +void freeList(Link head) { + Link p, x; + for (p = head, x = head->next; x != NULL; p = x, x = x->next){ + freeNode(p); + } +} + +#endif \ No newline at end of file diff --git a/Laboratorio 4/Esercizio 2/item.h b/Laboratorio 4/Esercizio 2/item.h new file mode 100644 index 0000000..128906a --- /dev/null +++ b/Laboratorio 4/Esercizio 2/item.h @@ -0,0 +1,55 @@ +// Laboratorio 4 - Esercizio 2 - item.h +// Matteo Schiff - s295565 + +#ifndef ITEM_H_DEFINED +#define ITEM_H_DEFINED + +#define CODE_LEN 5 +#define STR_LEN 50 + +typedef struct date_s { + int day; + int month; + int year; +} Date; + +typedef struct item_s { + char code[CODE_LEN+1]; + char name[STR_LEN+1]; + char surname[STR_LEN+1]; + Date date; + char address[STR_LEN+1]; + char city[STR_LEN+1]; + int cap; +} *Item; + +typedef struct node_s *Link; +typedef struct node_s { + Item val; + Link next; +} Node; + +typedef char* Key; + +// Date + +int DateGreater(Date a, Date b); + +// Item + +Item ItemFromString(char *str); +Item ItemRead(FILE * fp); +Key ItemKey(Item item); +int ItemEq(Key x, Key y); +void ItemPrint(FILE *fp, Item x); + +// List + +Link insertOrderedByDate(Item val, Link head); +Item getItemByCode(Link head, Key key); +void printList(FILE *fp, Link head); +Item extractCode(Link *headp, Key key); +Item extractDates(Link *headp, Date first, Date last); +void freeList(Link head); + +#endif \ No newline at end of file diff --git a/Laboratorio 4/Esercizio 2/main.c b/Laboratorio 4/Esercizio 2/main.c new file mode 100644 index 0000000..81ac670 --- /dev/null +++ b/Laboratorio 4/Esercizio 2/main.c @@ -0,0 +1,220 @@ +// Laboratorio 4 - Esercizio 2 - main.c +// Matteo Schiff - s295565 + +#include +#include +#include +#include +#include +#include "item.h" +#define MAX_LEN 30 + +const int MAXL = 100; + +typedef enum +{ + k_codice_tratta, + k_partenza, + k_destinazione, + k_data +} corsa_keys; + +typedef enum +{ + r_leggi_file, + r_leggi_tastiera, + r_ricerca_codice, + r_cancella_codice, + r_cancella_date, + r_stampa, + r_fine +} t_comandi; + +// Trasforma in lowercase tutti i caratteri di una stringa +char *toLower(char *s) +{ + for (char *p = s; *p; p++) + *p = tolower(*p); + return s; +} + +t_comandi leggiComando() +{ + t_comandi c; + char cmd[MAXL]; + char tabella[7][20] = { + "leggi_file", "leggi_tastiera", "ricerca_codice", "cancella_codice", "cancella_date", "stampa", "fine"}; + printf("comando (leggi_file/leggi_tastiera/ricerca_codice"); + printf("/cancella_codice/cancella_date/stampa/fine): "); + scanf("%s", cmd); + toLower(cmd); + c = r_leggi_file; + while (c < 8 && strcmp(cmd, tabella[c]) != 0) + c++; + return (c); +} + +void carica_file(char *argomenti, Link * head) +{ + char filename[MAX_LEN+1]; + FILE *fp_read; + if (sscanf(argomenti, " %30s", filename) != 1) + { + puts("Sintassi non valida. La sintassi è 'carica '"); + return; + } + + puts("Carico il nuovo file..."); + + if ((fp_read = fopen(filename, "r")) == NULL) + { + puts("Impossibile aprire il file"); + return; + } + + while(!feof(fp_read)) { + Item nuovo = ItemRead(fp_read); + // skip invalid entries + if (nuovo != NULL) + *head = insertOrderedByDate(nuovo, *head); + } + + fclose(fp_read); +} + +void carica_tastiera(char *argomenti, Link * head) +{ + Item new = ItemFromString(argomenti); + + if (new == NULL) { + puts("Anagrafica non valida"); + return; + } + + *head = insertOrderedByDate(new, *head); +} + +void ricerca_codice(char *argomenti, Link * head) +{ + char codice[CODE_LEN+1]; + if (sscanf(argomenti, " %5s", codice) != 1) + { + puts("Sintassi non valida. La sintassi è 'ricerca_codice '"); + return; + } + + Item found = getItemByCode(*head, codice); + + if (found == NULL) { + puts("Non è stato trovato nessun elemento"); + return; + } + + ItemPrint(stdout, found); +} + +void cancella_codice(char *argomenti, Link * head) +{ + char codice[CODE_LEN+1]; + if (sscanf(argomenti, " %5s", codice) != 1) + { + puts("Sintassi non valida. La sintassi è 'cancella_codice '"); + return; + } + + Item found = extractCode(head, codice); + + if (found == NULL) { + puts("Non è stato trovato nessun elemento"); + return; + } + + ItemPrint(stdout, found); + free(found); +} + +void cancella_date(char *argomenti, Link * head) +{ + Date start, end; + if (sscanf(argomenti, " %d/%d/%d %d/%d/%d", &(start.day), &(start.month), &(start.year), &(end.day), &(end.month), &(end.year)) != 6) + { + puts("Sintassi non valida. La sintassi è 'cancella_date '"); + return; + } + + Item found; + + while (found = extractDates(head, start, end), found != NULL) { + ItemPrint(stdout, found); + free(found); + } +} + +void stampa_file(char *argomenti, Link * head) +{ + FILE *fp_write; + char filename[MAX_LEN+1]; + if (sscanf(argomenti, " %30s", filename) != 1) + { + puts("Sintassi non valida. La sintassi è 'stampa '"); + return; + } + + + if ((fp_write = fopen(filename, "w")) == NULL) + { + puts("Impossibile aprire il file"); + return; + } + + printList(fp_write, *head); + fclose(fp_write); +} + +void menuParola(Link * head) +{ + t_comandi comando; + char argomenti[MAXL]; + int i, continua = 1; + while (continua) + { + comando = leggiComando(); + fgets(argomenti, MAXL, stdin); /* resto della riga */ + switch (comando) + { + case r_leggi_file: + carica_file(argomenti, head); + break; + case r_leggi_tastiera: + carica_tastiera(argomenti, head); + break; + case r_ricerca_codice: + ricerca_codice(argomenti, head); + break; + case r_cancella_codice: + cancella_codice(argomenti, head); + break; + case r_cancella_date: + cancella_date(argomenti, head); + break; + case r_stampa: + stampa_file(argomenti, head); + break; + case r_fine: + continua = 0; + break; + default: + puts("Comando non valido\n"); + } + } +} + +int main() +{ + Link head = NULL; + + menuParola(&head); + freeList(head); + + return 0; +} diff --git a/Laboratorio 4/Esercizio 2/out b/Laboratorio 4/Esercizio 2/out new file mode 100644 index 0000000..a55d8ee --- /dev/null +++ b/Laboratorio 4/Esercizio 2/out @@ -0,0 +1,2 @@ +A0004 Anna Gialli 04/09/1995 FratelliAlinari Firenze 50123 +A0002 Lucia Verdi 07/11/1989 ViaTorino Milano 20123 diff --git a/Laboratorio 4/Esercizio 3/easy_test_set.txt b/Laboratorio 4/Esercizio 3/easy_test_set.txt new file mode 100644 index 0000000..a68c17b --- /dev/null +++ b/Laboratorio 4/Esercizio 3/easy_test_set.txt @@ -0,0 +1,17 @@ +15 +5 7 4 10 +6 8 10 1 +3 1 6 10 +4 4 2 1 +7 2 4 10 +8 8 4 6 +6 1 4 4 +8 3 6 4 +7 7 4 2 +1 3 7 1 +10 10 9 10 +8 8 8 6 +9 6 10 5 +6 10 9 5 +9 6 9 9 + diff --git a/Laboratorio 4/Esercizio 3/easy_test_set_result.txt b/Laboratorio 4/Esercizio 3/easy_test_set_result.txt new file mode 100644 index 0000000..c1ed326 --- /dev/null +++ b/Laboratorio 4/Esercizio 3/easy_test_set_result.txt @@ -0,0 +1,45 @@ +TEST #1 +zaffiro = 5, rubino = 7, topazio = 4, smeraldo = 10, TOT = 26 +Collana massima di lunghezza 24 +TEST #2 +zaffiro = 6, rubino = 8, topazio = 10, smeraldo = 1, TOT = 25 +Collana massima di lunghezza 24 +TEST #3 +zaffiro = 3, rubino = 1, topazio = 6, smeraldo = 10, TOT = 20 +Collana massima di lunghezza 16 +TEST #4 +zaffiro = 4, rubino = 4, topazio = 2, smeraldo = 1, TOT = 11 +Collana massima di lunghezza 10 +TEST #5 +zaffiro = 7, rubino = 2, topazio = 4, smeraldo = 10, TOT = 23 +Collana massima di lunghezza 22 +TEST #6 +zaffiro = 8, rubino = 8, topazio = 4, smeraldo = 6, TOT = 26 +Collana massima di lunghezza 23 +TEST #7 +zaffiro = 6, rubino = 1, topazio = 4, smeraldo = 4, TOT = 15 +Collana massima di lunghezza 13 +TEST #8 +zaffiro = 8, rubino = 3, topazio = 6, smeraldo = 4, TOT = 21 +Collana massima di lunghezza 19 +TEST #9 +zaffiro = 7, rubino = 7, topazio = 4, smeraldo = 2, TOT = 20 +Collana massima di lunghezza 18 +TEST #10 +zaffiro = 1, rubino = 3, topazio = 7, smeraldo = 1, TOT = 12 +Collana massima di lunghezza 9 +TEST #11 +zaffiro = 10, rubino = 10, topazio = 9, smeraldo = 10, TOT = 39 +Collana massima di lunghezza 39 +TEST #12 +zaffiro = 8, rubino = 8, topazio = 8, smeraldo = 6, TOT = 30 +Collana massima di lunghezza 30 +TEST #13 +zaffiro = 9, rubino = 6, topazio = 10, smeraldo = 5, TOT = 30 +Collana massima di lunghezza 27 +TEST #14 +zaffiro = 6, rubino = 10, topazio = 9, smeraldo = 5, TOT = 30 +Collana massima di lunghezza 30 +TEST #15 +zaffiro = 9, rubino = 6, topazio = 9, smeraldo = 9, TOT = 33 +Collana massima di lunghezza 31 diff --git a/Laboratorio 4/Esercizio 3/hard_test_set.txt b/Laboratorio 4/Esercizio 3/hard_test_set.txt new file mode 100644 index 0000000..6ecdc7e --- /dev/null +++ b/Laboratorio 4/Esercizio 3/hard_test_set.txt @@ -0,0 +1,16 @@ +15 +19 6 8 5 +19 14 5 11 +14 14 5 8 +12 16 5 14 +12 17 20 20 +13 11 14 18 +7 14 12 10 +13 20 12 17 +17 18 6 9 +5 5 15 19 +18 12 20 17 +13 6 19 6 +17 20 15 19 +12 18 17 8 +7 20 12 7 diff --git a/Laboratorio 4/Esercizio 3/hard_test_set_result.txt b/Laboratorio 4/Esercizio 3/hard_test_set_result.txt new file mode 100644 index 0000000..8178b4d --- /dev/null +++ b/Laboratorio 4/Esercizio 3/hard_test_set_result.txt @@ -0,0 +1,45 @@ +TEST #1 +zaffiro = 19, rubino = 6, topazio = 8, smeraldo = 5, TOT = 38 +Collana massima di lunghezza 37 +TEST #2 +zaffiro = 19, rubino = 14, topazio = 5, smeraldo = 11, TOT = 49 +Collana massima di lunghezza 41 +TEST #3 +zaffiro = 14, rubino = 14, topazio = 5, smeraldo = 8, TOT = 41 +Collana massima di lunghezza 33 +TEST #4 +zaffiro = 12, rubino = 16, topazio = 5, smeraldo = 14, TOT = 47 +Collana massima di lunghezza 37 +TEST #5 +zaffiro = 12, rubino = 17, topazio = 20, smeraldo = 20, TOT = 69 +Collana massima di lunghezza 67 +TEST #6 +zaffiro = 13, rubino = 11, topazio = 14, smeraldo = 18, TOT = 56 +Collana massima di lunghezza 54 +TEST #7 +zaffiro = 7, rubino = 14, topazio = 12, smeraldo = 10, TOT = 43 +Collana massima di lunghezza 42 +TEST #8 +zaffiro = 13, rubino = 20, topazio = 12, smeraldo = 17, TOT = 62 +Collana massima di lunghezza 55 +TEST #9 +zaffiro = 17, rubino = 18, topazio = 6, smeraldo = 9, TOT = 50 +Collana massima di lunghezza 39 +TEST #10 +zaffiro = 5, rubino = 5, topazio = 15, smeraldo = 19, TOT = 44 +Collana massima di lunghezza 35 +TEST #11 +zaffiro = 18, rubino = 12, topazio = 20, smeraldo = 17, TOT = 67 +Collana massima di lunghezza 60 +TEST #12 +zaffiro = 13, rubino = 6, topazio = 19, smeraldo = 6, TOT = 44 +Collana massima di lunghezza 32 +TEST #13 +zaffiro = 17, rubino = 20, topazio = 15, smeraldo = 19, TOT = 71 +Collana massima di lunghezza 67 +TEST #14 +zaffiro = 12, rubino = 18, topazio = 17, smeraldo = 8, TOT = 55 +Collana massima di lunghezza 55 +TEST #15 +zaffiro = 7, rubino = 20, topazio = 12, smeraldo = 7, TOT = 46 +Collana massima di lunghezza 39 diff --git a/Laboratorio 4/Esercizio 3/main.c b/Laboratorio 4/Esercizio 3/main.c new file mode 100644 index 0000000..de3e071 --- /dev/null +++ b/Laboratorio 4/Esercizio 3/main.c @@ -0,0 +1,107 @@ +// Laboratorio 4 - Esercizio 3 - main.c +// Matteo Schiff - s295565 + +#include +#include +#include + +enum Pietra{zaffiro, rubino, topazio, smeraldo}; + +// Esploro il set di collane valide in modo ordinato, quando arrivo alla fine della collana ne controllo +// la lunghezza e aggiorno se necessario la soluzione +void esploraSoluzioni(int z, int r, int t, int s, int len, int * tmp, int * max, int * sol) { + int added = false; + if (z > 0 && (len == 0 || (tmp[len - 1] == zaffiro || tmp[len - 1] == topazio))) { + tmp[len] = zaffiro; + esploraSoluzioni(z-1,r,t,s,len +1,tmp,max,sol); + added = true; + } + + if (s > 0 && (len == 0 || (tmp[len - 1] == smeraldo || tmp[len - 1] == rubino))) { + tmp[len] = smeraldo; + esploraSoluzioni(z,r,t,s-1,len +1,tmp,max,sol); + added = true; + } + + if (r > 0 && (len == 0 || (tmp[len - 1] == zaffiro || tmp[len - 1] == topazio))) { + tmp[len] = rubino; + esploraSoluzioni(z,r-1,t,s,len +1,tmp,max,sol); + added = true; + } + + if (t > 0 && (len == 0 || (tmp[len - 1] == smeraldo || tmp[len - 1] == rubino))) { + tmp[len] = topazio; + esploraSoluzioni(z,r,t-1,s,len +1,tmp,max,sol); + added = true; + } + + // se non è possibile più aggiungere pietre, ho raggiunto la lunghezza massima ottenibile dal ramo + if (!added) { + if (len > *max) { + *max = len; + for (int i = 0; i < len; i++) { + sol[i] = tmp[i]; + } + } + } +} + +void solveCase(int z, int r, int t, int s) { + int maxL = z+r+t+s; + int max = 0; + // vettore su cui la funzione costruisce le collane + int * tmp = malloc(maxL * sizeof(int)); + // vettore utilizzato per memorizzare la soluzione + int * sol = malloc(maxL * sizeof(int)); + + printf("zaffiri = %d, rubini = %d, topazi = %d, smeraldi = %d; numero pietre = %d\n", z,r,t,s,maxL); + + esploraSoluzioni(z,r,t,s,0,tmp,&max,sol); + + printf("Collana massima di lunghezza %d\n", max); + for(int i = 0; i < max; i++) { + switch (sol[i]) + { + case zaffiro: + printf("z "); + break; + case rubino: + printf("r "); + break; + case smeraldo: + printf("s "); + break; + case topazio: + printf("t "); + break; + default: + break; + } + } + putc('\n', stdout); + fflush(stdout); + free(tmp); + free(sol); +} + +int main() { + int z, r, t, s, N = 0; + + FILE *fp; + + if ((fp = fopen("easy_test_set.txt", "r")) == NULL) + { + puts("Impossibile aprire il file"); + return 1; + } + + fscanf(fp, "%d", &N); + + for (int i = 0; i < N; i++) { + fscanf(fp, " %d %d %d %d", &z, &r, &t, &s); + printf("Test case %d\n", i+1); + solveCase(z,r,t,s); + } + + fclose(fp); +} \ No newline at end of file diff --git a/Laboratorio 4/Esercizio 3/very_easy_test_set.txt b/Laboratorio 4/Esercizio 3/very_easy_test_set.txt new file mode 100644 index 0000000..e90b82a --- /dev/null +++ b/Laboratorio 4/Esercizio 3/very_easy_test_set.txt @@ -0,0 +1,7 @@ +6 +2 1 2 2 +3 2 3 3 +6 2 2 3 +6 4 4 3 +4 3 7 4 +6 5 9 7 \ No newline at end of file diff --git a/Laboratorio 4/Esercizio 3/very_very_easy_test_set.txt b/Laboratorio 4/Esercizio 3/very_very_easy_test_set.txt new file mode 100644 index 0000000..a28453b --- /dev/null +++ b/Laboratorio 4/Esercizio 3/very_very_easy_test_set.txt @@ -0,0 +1,3 @@ +1 +2 1 2 2 + diff --git a/Laboratorio 4/Esercizio 4/main.c b/Laboratorio 4/Esercizio 4/main.c new file mode 100644 index 0000000..8a01718 --- /dev/null +++ b/Laboratorio 4/Esercizio 4/main.c @@ -0,0 +1,122 @@ +// Laboratorio 4 - Esercizio 4 - item.c +// Matteo Schiff - s295565 + +#include +#include +#include + +enum Pietra{zaffiro, rubino, topazio, smeraldo}; + +// Ho messo queste variabili globali per diminuire il numero di parametri +// di `esploraSoluzioni` per migliorarne la leggibilità +// Questi numeri sono costanti per ogni set +int vz, vr, vt, vs, max_rip; + +void esploraSoluzioni(int z, int r, int t, int s, int nz, int ns, int cur_rip, int len, int val, int * tmp, int * max, int*maxlen, int * sol) { + int added = false; + if (z > 0 && (nz +1) <= ns) { + tmp[len] = zaffiro; + if (len == 0 || tmp[len - 1] == topazio) { + esploraSoluzioni(z-1,r,t,s,nz+1,ns,1,len +1,val+vz,tmp,max,maxlen,sol); + added = true; + } + if (len != 0 && tmp[len - 1] == zaffiro && cur_rip < max_rip) { + esploraSoluzioni(z-1,r,t,s,nz+1,ns,cur_rip+1,len +1,val+vz,tmp,max,maxlen,sol); + added = true; + } + } + + if (s > 0) { + tmp[len] = smeraldo; + if (len == 0 || tmp[len - 1] == rubino) { + esploraSoluzioni(z,r,t,s-1,nz,ns+1,1,len +1,val+vs,tmp,max,maxlen,sol); + added = true; + } + if (len != 0 && tmp[len - 1] == smeraldo && cur_rip < max_rip) { + esploraSoluzioni(z,r,t,s-1,nz,ns+1,cur_rip+1,len +1,val+vs,tmp,max,maxlen,sol); + added = true; + } + } + + if (r > 0 && (len == 0 || (tmp[len - 1] == zaffiro || tmp[len - 1] == topazio))) { + tmp[len] = rubino; + esploraSoluzioni(z,r-1,t,s,nz,ns,1,len +1,val+vr,tmp,max,maxlen,sol); + added = true; + } + + if (t > 0 && (len == 0 || (tmp[len - 1] == smeraldo || tmp[len - 1] == rubino))) { + tmp[len] = topazio; + esploraSoluzioni(z,r,t-1,s,nz,ns,1,len +1,val+vt,tmp,max,maxlen,sol); + added = true; + } + + // se non è possibile più aggiungere pietre, ho raggiunto la lunghezza massima ottenibile dal ramo + if (!added) { + if (val >= *max) { + *max = val; + *maxlen = len; + for (int i = 0; i < len; i++) { + sol[i] = tmp[i]; + } + } + } +} + +void solveCase(int z, int r, int t, int s) { + int maxL = z+r+t+s; + int max = 0; + int maxlen = 0; + int * tmp = malloc(maxL * sizeof(int)); + int * sol = malloc(maxL * sizeof(int)); + + printf("zaffiri = %d (valore: %d), rubini = %d (valore: %d), topazi = %d (valore: %d), smeraldi = %d (valore: %d); numero pietre = %d {max_rip = %d}\n", z, vz,r,vr,t,vt,s,vs,maxL, max_rip); + + esploraSoluzioni(z,r,t,s,0,0,0,0,0,tmp,&max,&maxlen,sol); + + printf("Collana con valore massimo %d, lunghezza %d\n", max, maxlen); + for(int i = 0; i < maxlen; i++) { + switch (sol[i]) + { + case zaffiro: + printf("z "); + break; + case rubino: + printf("r "); + break; + case smeraldo: + printf("s "); + break; + case topazio: + printf("t "); + break; + default: + break; + } + } + putc('\n', stdout); + fflush(stdout); + free(tmp); + free(sol); +} + +int main() { + int z, r, t, s, N = 0; + + FILE *fp; + + if ((fp = fopen("test_set.txt", "r")) == NULL) + { + puts("Impossibile aprire il file"); + return 1; + } + + fscanf(fp, "%d", &N); + + for (int i = 0; i < N; i++) { + fscanf(fp, " %d %d %d %d %d %d %d %d %d", &z, &r, &t, &s, &vz, &vr, &vt, &vs, &max_rip); + printf("Test case %d\n", i+1); + solveCase(z,r,t,s); + } + + fclose(fp); +} \ No newline at end of file diff --git a/Laboratorio 4/Esercizio 4/test_set.txt b/Laboratorio 4/Esercizio 4/test_set.txt new file mode 100644 index 0000000..c22915c --- /dev/null +++ b/Laboratorio 4/Esercizio 4/test_set.txt @@ -0,0 +1,21 @@ +20 +8 1 10 5 6 6 20 8 3 +6 5 7 2 2 15 2 21 5 +10 7 8 10 17 16 18 17 3 +7 1 9 2 10 13 16 20 5 +6 6 8 10 8 25 20 10 7 +5 6 1 5 21 7 13 1 9 +9 5 3 8 7 3 10 8 6 +7 8 6 8 5 5 12 15 5 +4 8 8 6 1 19 13 19 1 +9 3 9 9 17 11 3 5 7 +1 1 5 10 15 12 14 15 6 +2 9 3 5 19 14 6 19 3 +4 5 2 7 21 10 16 5 10 +5 6 9 6 20 14 3 17 4 +9 8 9 2 17 5 21 11 9 +7 1 3 6 25 19 3 20 8 +6 2 5 4 19 22 3 11 8 +9 3 5 3 3 1 2 24 9 +5 10 7 9 19 1 6 5 1 +4 8 2 10 13 1 8 23 3 \ No newline at end of file diff --git a/Laboratorio 4/Esercizio 4/test_set_results.txt b/Laboratorio 4/Esercizio 4/test_set_results.txt new file mode 100644 index 0000000..c601cbe --- /dev/null +++ b/Laboratorio 4/Esercizio 4/test_set_results.txt @@ -0,0 +1,80 @@ +TEST #1 +zaffiro = 8 [6], rubino = 1 [6], topazio = 10 [20], smeraldo = 5 [8], TOT = 24 {max_rip = 3} +Soluzione ottima di valore 116 usando 13 gemma/e +Composizione collana: sstzzrssstzzz +TEST #2 +zaffiro = 6 [2], rubino = 5 [15], topazio = 7 [2], smeraldo = 2 [21], TOT = 20 {max_rip = 5} +Soluzione ottima di valore 133 usando 15 gemma/e +Composizione collana: trtrtrtrtrsstzz +TEST #3 +zaffiro = 10 [17], rubino = 7 [16], topazio = 8 [18], smeraldo = 10 [17], TOT = 35 {max_rip = 3} +Soluzione ottima di valore 596 usando 35 gemma/e +Composizione collana: trtrtrtrstzrssstzzzrssstzzzrssstzzz +TEST #4 +zaffiro = 7 [10], rubino = 1 [13], topazio = 9 [16], smeraldo = 2 [20], TOT = 19 {max_rip = 5} +Soluzione ottima di valore 105 usando 7 gemma/e +Composizione collana: trsstzz +TEST #5 +zaffiro = 6 [8], rubino = 6 [25], topazio = 8 [20], smeraldo = 10 [10], TOT = 30 {max_rip = 7} +Soluzione ottima di valore 438 usando 29 gemma/e +Composizione collana: trtrtrtrtrssstzzzrssssssstzzz +TEST #6 +zaffiro = 5 [21], rubino = 6 [7], topazio = 1 [13], smeraldo = 5 [1], TOT = 17 {max_rip = 9} +Soluzione ottima di valore 137 usando 13 gemma/e +Composizione collana: rssssstzzzzzr +TEST #7 +zaffiro = 9 [7], rubino = 5 [3], topazio = 3 [10], smeraldo = 8 [8], TOT = 25 {max_rip = 6} +Soluzione ottima di valore 162 usando 23 gemma/e +Composizione collana: rtrsstzzrsssssstzzzzzzr +TEST #8 +zaffiro = 7 [5], rubino = 8 [5], topazio = 6 [12], smeraldo = 8 [15], TOT = 29 {max_rip = 5} +Soluzione ottima di valore 262 usando 28 gemma/e +Composizione collana: rtrtrtrtrsstzzrssssstzzzzzrs +TEST #9 +zaffiro = 4 [1], rubino = 8 [19], topazio = 8 [13], smeraldo = 6 [19], TOT = 26 {max_rip = 1} +Soluzione ottima di valore 374 usando 26 gemma/e +Composizione collana: rtrtrstzrstzrstzrstzrstrst +TEST #10 +zaffiro = 9 [17], rubino = 3 [11], topazio = 9 [3], smeraldo = 9 [5], TOT = 30 {max_rip = 7} +Soluzione ottima di valore 243 usando 25 gemma/e +Composizione collana: trtrsstzzrssssssstzzzzzzz +TEST #11 +zaffiro = 1 [15], rubino = 1 [12], topazio = 5 [14], smeraldo = 10 [15], TOT = 17 {max_rip = 6} +Soluzione ottima di valore 205 usando 14 gemma/e +Composizione collana: sssstzrsssssst +TEST #12 +zaffiro = 2 [19], rubino = 9 [14], topazio = 3 [6], smeraldo = 5 [19], TOT = 19 {max_rip = 3} +Soluzione ottima di valore 207 usando 14 gemma/e +Composizione collana: rtrtrsstzzrsss +TEST #13 +zaffiro = 4 [21], rubino = 5 [10], topazio = 2 [16], smeraldo = 7 [5], TOT = 18 {max_rip = 10} +Soluzione ottima di valore 181 usando 16 gemma/e +Composizione collana: rtrsssstzzzzrsss +TEST #14 +zaffiro = 5 [20], rubino = 6 [14], topazio = 9 [3], smeraldo = 6 [17], TOT = 26 {max_rip = 4} +Soluzione ottima di valore 307 usando 24 gemma/e +Composizione collana: trtrtrtrtrsstzzrsssstzzz +TEST #15 +zaffiro = 9 [17], rubino = 8 [5], topazio = 9 [21], smeraldo = 2 [11], TOT = 28 {max_rip = 9} +Soluzione ottima di valore 285 usando 21 gemma/e +Composizione collana: trtrtrtrtrtrtrtrsstzz +TEST #16 +zaffiro = 7 [25], rubino = 1 [19], topazio = 3 [3], smeraldo = 6 [20], TOT = 17 {max_rip = 8} +Soluzione ottima di valore 295 usando 15 gemma/e +Composizione collana: trsssssstzzzzzz +TEST #17 +zaffiro = 6 [19], rubino = 2 [22], topazio = 5 [3], smeraldo = 4 [11], TOT = 17 {max_rip = 8} +Soluzione ottima di valore 173 usando 13 gemma/e +Composizione collana: trtrsssstzzzz +TEST #18 +zaffiro = 9 [3], rubino = 3 [1], topazio = 5 [2], smeraldo = 3 [24], TOT = 20 {max_rip = 9} +Soluzione ottima di valore 92 usando 13 gemma/e +Composizione collana: trtrtrssstzzz +TEST #19 +zaffiro = 5 [19], rubino = 10 [1], topazio = 7 [6], smeraldo = 9 [5], TOT = 31 {max_rip = 1} +Soluzione ottima di valore 185 usando 28 gemma/e +Composizione collana: rstzrstzrstzrstzrstzrstrstrs +TEST #20 +zaffiro = 4 [13], rubino = 8 [1], topazio = 2 [8], smeraldo = 10 [23], TOT = 24 {max_rip = 3} +Soluzione ottima di valore 278 usando 18 gemma/e +Composizione collana: rssstzzzrssstzrsss \ No newline at end of file diff --git a/Laboratorio 5/Esercizio 1/att.txt b/Laboratorio 5/Esercizio 1/att.txt new file mode 100644 index 0000000..aceffaa --- /dev/null +++ b/Laboratorio 5/Esercizio 1/att.txt @@ -0,0 +1,7 @@ +6 +1 2 +2 4 +2 5 +3 5 +5 7 +6 8 diff --git a/Laboratorio 5/Esercizio 1/att1.txt b/Laboratorio 5/Esercizio 1/att1.txt new file mode 100644 index 0000000..99cf558 --- /dev/null +++ b/Laboratorio 5/Esercizio 1/att1.txt @@ -0,0 +1,9 @@ +8 +0 6 +1 4 +3 5 +3 8 +4 7 +5 9 +6 10 +8 11 \ No newline at end of file diff --git a/Laboratorio 5/Esercizio 1/main.c b/Laboratorio 5/Esercizio 1/main.c new file mode 100644 index 0000000..2db852c --- /dev/null +++ b/Laboratorio 5/Esercizio 1/main.c @@ -0,0 +1,103 @@ +// Laboratorio 5 - Esercizio 1 +// Matteo Schiff - s295565 + +#include +#include + +typedef struct { + int start, end; +} att; + +void readFile(att **val, int *N, char *filename) { + FILE *fp; + + if ((fp = fopen(filename, "r")) == NULL) { + printf("Impossibile aprire il file di input %s", filename); + exit(1); + } + + fscanf(fp, "%d", N); + + *val = (att *) malloc(*N * sizeof(att)); + for (int i = 0; i < *N; i++) { + fscanf(fp, "%d %d", &(*val)[i].start, &(*val)[i].end); + } + + fclose(fp); +} + +int controllaCompatibile(att *val, int N, int pos, int *selezioni) { + int compatibile = 1; + att last = val[pos]; + + for (int i = 0; i < N && compatibile; i++) { + if (i != pos && selezioni[i] == 1) { + if (val[i].start < last.end && last.start < val[i].end) + compatibile = 0; + } + } + return compatibile; +} + +void stampaSoluzione(int *soluzione, att *val, int N) { + for (int i = 0; i < N; i++) { + if (soluzione[i] == 1) { + printf("(%d, %d) ", val[i].start, val[i].end); + } + } + printf("\n"); +} + +void attSelR(int N, att *val, int pos, int *selezioni, int *soluzione, int durata, int *durata_soluzione) { + // Terminazione + if (pos >= N) { + if (durata > *durata_soluzione) { + *durata_soluzione = durata; + // copio nuova soluzione + for (int i = 0; i < N; i++) { + soluzione[i] = selezioni[i]; + } + } + return; + } + + // inserisco un attività solo se è compatibile con il resto della soluzione + if (controllaCompatibile(val, N, pos, selezioni)) { + selezioni[pos] = 1; + int d = val[pos].end - val[pos].start; + attSelR(N, val, pos+1, selezioni,soluzione, durata+d, durata_soluzione); + } + + // continuo ad esplorare senza prendere l'attività + selezioni[pos] = 0; + attSelR(N, val, pos+1, selezioni,soluzione, durata, durata_soluzione); + + return; +} + +void attSel(int N, att *v) { + int durata_soluzione = 0; + + int *selezioni = (int *) calloc(N, sizeof(int)); + int *soluzione = (int *) calloc(N, sizeof(int)); + + attSelR(N, v, 0, selezioni, soluzione, 0, &durata_soluzione); + printf("Migliore soluzione:\n"); + stampaSoluzione(soluzione, v, N); + printf("Durata della migliore soluzione: %d\n", durata_soluzione); + + free(selezioni); + free(soluzione); +} + +int main(int argc, char const *argv[]) +{ + att *val; + int N; + + readFile(&val, &N, "att.txt"); + attSel(N, val); + free(val); + + return 0; +} diff --git a/Laboratorio 5/Esercizio 2/board.txt b/Laboratorio 5/Esercizio 2/board.txt new file mode 100644 index 0000000..e05fc29 --- /dev/null +++ b/Laboratorio 5/Esercizio 2/board.txt @@ -0,0 +1,4 @@ +3 3 +0/0 -1/-1 2/0 +3/1 -1/-1 -1/-1 +-1/-1 6/0 -1/-1 diff --git a/Laboratorio 5/Esercizio 2/main.c b/Laboratorio 5/Esercizio 2/main.c new file mode 100644 index 0000000..2f8dffe --- /dev/null +++ b/Laboratorio 5/Esercizio 2/main.c @@ -0,0 +1,245 @@ +// Laboratorio 5 - Esercizio 2 +// Matteo Schiff - s295565 + +#include +#include +#include + +typedef struct tile_s { + char c_o, c_v; // colore orizzontale e verticale + int p_o, p_v; // punti orizzontali e verticali +} tile; + +typedef struct cell_s { + int id, rot; // id tile e rotazione +} cell; + +void readTiles(tile **tiles, int *N, char *filename) { + FILE *fp; + + if ((fp = fopen(filename, "r")) == NULL) { + printf("Errore nell'apertura del file %s",filename); + exit(1); + } + + fscanf(fp, "%d", N); + + *tiles = (tile *) malloc(*N * sizeof(tile)); + for (int i = 0; i < *N; i++) { + fscanf(fp, " %c %d %c %d", &((*tiles)[i].c_o), &((*tiles)[i].p_o), &((*tiles)[i].c_v), &((*tiles)[i].p_v)); + } + + fclose(fp); +} + +void readBoard(cell ***board, int *R, int *C, char *filename) { + FILE *fp; + + if ((fp = fopen(filename, "r")) == NULL) { + printf("Errore nell'apertura del file %s",filename); + exit(1); + } + + fscanf(fp, "%d %d", R, C); + + *board = (cell **) malloc(*R * sizeof(cell *)); + for (int i = 0; i < *R; i++) { + (*board)[i] = (cell *) malloc(*C * sizeof(cell)); + for (int j = 0; j < *C; j++) { + fscanf(fp, " %d/%d", &(*board)[i][j].id, &(*board)[i][j].rot); + } + } + + fclose(fp); +} + +// funzione helper per ottenere il colore di un tile conoscendone la posizione +// se `vert` è true restituisce il colore sulla verticale +char getTileColor(tile *tiles, cell **board, int x, int y, bool vert) { + cell c = board[x][y]; + + if (c.rot ^ vert) + return tiles[c.id].c_v; + + return tiles[c.id].c_o; +} + +// funzione helper per ottenere il punteggio di un tile conoscendone la posizione +// se `vert` è true restituisce il punteggio sulla verticale +char getTilePoints(tile *tiles, cell **board, int x, int y, bool vert) { + cell c = board[x][y]; + + if (c.rot ^ vert) + return tiles[c.id].p_v; + + return tiles[c.id].p_o; +} + +int calcolaPunteggio(int R, int C, tile *tiles, cell **board) { + int points = 0; + for (int i = 0; i < R; i++) { + char color = getTileColor(tiles, board, i, 0, false); + int temp_points = getTilePoints(tiles, board, i, 0, false); + bool ok = true; + + for (int j = 1; ok && j < C; j++) { + if (color != getTileColor(tiles, board, i, j, false)) + ok = false; + temp_points += getTilePoints(tiles, board, i, j, false); + } + + // Aggiungo i punti solo se la riga è dello stesso colore + if (ok) { + points += temp_points; + } + } + + for (int i = 0; i < C; i++) { + char color = getTileColor(tiles, board, 0, i, true); + int temp_points = getTilePoints(tiles, board, 0, i, true); + bool ok = true; + + for (int j = 1; ok && j < R; j++) { + if (color != getTileColor(tiles, board, j, i, true)) + ok = false; + temp_points += getTilePoints(tiles, board, j, i, true); + } + + // Aggiungo i punti solo se la colonna è dello stesso colore + if (ok) { + points += temp_points; + } + } + + return points; +} + +void cercaMassimoR(int R, int C, int N, tile *tiles, bool * taken, cell **board, int depth, int * max, cell **sol) { + // Terminazione + if (depth == R*C) { + int punteggio = calcolaPunteggio(R, C, tiles, board); + + if (punteggio > *max) { + *max = punteggio; + // Copio soluzione + for (int i = 0; i < R; i++) { + for (int j = 0; j < C; j++) { + sol[i][j] = board[i][j]; + } + } + } + + return; + } + + int r = depth / C; + int c = depth % C; + + // Provo ad aggiungere un tile solo se nella casella non è già presente un altro tile + if (board[r][c].id == -1 && board[r][c].rot == -1) { + for (int i = 0; i < N; i++) { + if (!taken[i]) { + taken[i] = true; + board[r][c].id = i; + // Aggiungo in un verso + board[r][c].rot = 0; + cercaMassimoR(R, C, N, tiles, taken, board, depth + 1, max, sol); + // Aggiungo nell'altro verso + board[r][c].rot = 1; + cercaMassimoR(R, C, N, tiles, taken, board, depth + 1, max, sol); + taken[i] = false; + } + } + // Pulisco la casella, in modo che nella esplorazione successiva + // la funzione inserisca un altra tessera + board[r][c].id = -1; + board[r][c].rot = -1; + } else { + cercaMassimoR(R, C, N, tiles, taken, board, depth + 1, max, sol); + } +} + +cell ** cercaMassimo(int R, int C, int N, tile *tiles, cell **board) { + int max = 0; + bool *taken = (bool *) malloc(N * sizeof(bool)); + + // Rimuovo dalla lista delle tessere disponibili quelle che sono già presenti sulla board + for (int i = 0; i < R; i++) { + for (int j = 0; j < C; j++) { + if (board[i][j].id != -1) + taken[board[i][j].id] = true; + } + } + + cell **solution = (cell **) malloc(R * sizeof(cell *)); + for (int i = 0; i < R; i++) { + solution[i] = (cell *) malloc(C * sizeof(cell)); + } + + cercaMassimoR(R,C,N,tiles,taken,board,0,&max,solution); + + free(taken); + return solution; +} + +void freeSolution(cell **solution, int R) { + for (int i = 0; i < R; i++) { + free(solution[i]); + } + free(solution); +} + +// Disegna la board +void printBoard(int R, int C, cell **board, tile * tiles) { + for (int i = 0; i < R; i++) { + for (int j = 0; j < C; j++) { + tile t = tiles[board[i][j].id]; + if (board[i][j].rot) { + printf(" %c ", t.c_o); + } else { + printf(" %c ", t.c_v); + } + } + putchar('\n'); + for (int j = 0; j < C; j++) { + tile t = tiles[board[i][j].id]; + if (board[i][j].rot) { + printf("%c %d ", t.c_v, t.p_v); + } else { + printf("%c %d ", t.c_o, t.p_o); + } + } + putchar('\n'); + for (int j = 0; j < C; j++) { + tile t = tiles[board[i][j].id]; + if (board[i][j].rot) { + printf(" %d ", t.p_o); + } else { + printf(" %d ", t.p_v); + } + } + putchar('\n'); + putchar('\n'); + } +} + + +int main(int argc, char const *argv[]) +{ + tile *tiles; + cell **board; + int N, R, C; + + readTiles(&tiles, &N, "tiles.txt"); + readBoard(&board, &R, &C, "board.txt"); + + cell **solution = cercaMassimo(R,C,N,tiles,board); + + printBoard(R, C, solution, tiles); + + freeSolution(solution, R); + free(tiles); + free(board); + + return 0; +} diff --git a/Laboratorio 5/Esercizio 2/tiles.txt b/Laboratorio 5/Esercizio 2/tiles.txt new file mode 100644 index 0000000..222c4e1 --- /dev/null +++ b/Laboratorio 5/Esercizio 2/tiles.txt @@ -0,0 +1,10 @@ +9 +A 3 B 2 +A 2 V 1 +A 2 V 2 +B 1 N 2 +A 3 G 3 +V 1 G 2 +R 1 G 6 +V 1 B 1 +V 11 B 3 diff --git a/Laboratorio 6/Esercizio 2/easy_test_set.txt b/Laboratorio 6/Esercizio 2/easy_test_set.txt new file mode 100644 index 0000000..a68c17b --- /dev/null +++ b/Laboratorio 6/Esercizio 2/easy_test_set.txt @@ -0,0 +1,17 @@ +15 +5 7 4 10 +6 8 10 1 +3 1 6 10 +4 4 2 1 +7 2 4 10 +8 8 4 6 +6 1 4 4 +8 3 6 4 +7 7 4 2 +1 3 7 1 +10 10 9 10 +8 8 8 6 +9 6 10 5 +6 10 9 5 +9 6 9 9 + diff --git a/Laboratorio 6/Esercizio 2/easy_test_set_result.txt b/Laboratorio 6/Esercizio 2/easy_test_set_result.txt new file mode 100644 index 0000000..c1ed326 --- /dev/null +++ b/Laboratorio 6/Esercizio 2/easy_test_set_result.txt @@ -0,0 +1,45 @@ +TEST #1 +zaffiro = 5, rubino = 7, topazio = 4, smeraldo = 10, TOT = 26 +Collana massima di lunghezza 24 +TEST #2 +zaffiro = 6, rubino = 8, topazio = 10, smeraldo = 1, TOT = 25 +Collana massima di lunghezza 24 +TEST #3 +zaffiro = 3, rubino = 1, topazio = 6, smeraldo = 10, TOT = 20 +Collana massima di lunghezza 16 +TEST #4 +zaffiro = 4, rubino = 4, topazio = 2, smeraldo = 1, TOT = 11 +Collana massima di lunghezza 10 +TEST #5 +zaffiro = 7, rubino = 2, topazio = 4, smeraldo = 10, TOT = 23 +Collana massima di lunghezza 22 +TEST #6 +zaffiro = 8, rubino = 8, topazio = 4, smeraldo = 6, TOT = 26 +Collana massima di lunghezza 23 +TEST #7 +zaffiro = 6, rubino = 1, topazio = 4, smeraldo = 4, TOT = 15 +Collana massima di lunghezza 13 +TEST #8 +zaffiro = 8, rubino = 3, topazio = 6, smeraldo = 4, TOT = 21 +Collana massima di lunghezza 19 +TEST #9 +zaffiro = 7, rubino = 7, topazio = 4, smeraldo = 2, TOT = 20 +Collana massima di lunghezza 18 +TEST #10 +zaffiro = 1, rubino = 3, topazio = 7, smeraldo = 1, TOT = 12 +Collana massima di lunghezza 9 +TEST #11 +zaffiro = 10, rubino = 10, topazio = 9, smeraldo = 10, TOT = 39 +Collana massima di lunghezza 39 +TEST #12 +zaffiro = 8, rubino = 8, topazio = 8, smeraldo = 6, TOT = 30 +Collana massima di lunghezza 30 +TEST #13 +zaffiro = 9, rubino = 6, topazio = 10, smeraldo = 5, TOT = 30 +Collana massima di lunghezza 27 +TEST #14 +zaffiro = 6, rubino = 10, topazio = 9, smeraldo = 5, TOT = 30 +Collana massima di lunghezza 30 +TEST #15 +zaffiro = 9, rubino = 6, topazio = 9, smeraldo = 9, TOT = 33 +Collana massima di lunghezza 31 diff --git a/Laboratorio 6/Esercizio 2/hard_test_set.txt b/Laboratorio 6/Esercizio 2/hard_test_set.txt new file mode 100644 index 0000000..6ecdc7e --- /dev/null +++ b/Laboratorio 6/Esercizio 2/hard_test_set.txt @@ -0,0 +1,16 @@ +15 +19 6 8 5 +19 14 5 11 +14 14 5 8 +12 16 5 14 +12 17 20 20 +13 11 14 18 +7 14 12 10 +13 20 12 17 +17 18 6 9 +5 5 15 19 +18 12 20 17 +13 6 19 6 +17 20 15 19 +12 18 17 8 +7 20 12 7 diff --git a/Laboratorio 6/Esercizio 2/hard_test_set_result.txt b/Laboratorio 6/Esercizio 2/hard_test_set_result.txt new file mode 100644 index 0000000..8178b4d --- /dev/null +++ b/Laboratorio 6/Esercizio 2/hard_test_set_result.txt @@ -0,0 +1,45 @@ +TEST #1 +zaffiro = 19, rubino = 6, topazio = 8, smeraldo = 5, TOT = 38 +Collana massima di lunghezza 37 +TEST #2 +zaffiro = 19, rubino = 14, topazio = 5, smeraldo = 11, TOT = 49 +Collana massima di lunghezza 41 +TEST #3 +zaffiro = 14, rubino = 14, topazio = 5, smeraldo = 8, TOT = 41 +Collana massima di lunghezza 33 +TEST #4 +zaffiro = 12, rubino = 16, topazio = 5, smeraldo = 14, TOT = 47 +Collana massima di lunghezza 37 +TEST #5 +zaffiro = 12, rubino = 17, topazio = 20, smeraldo = 20, TOT = 69 +Collana massima di lunghezza 67 +TEST #6 +zaffiro = 13, rubino = 11, topazio = 14, smeraldo = 18, TOT = 56 +Collana massima di lunghezza 54 +TEST #7 +zaffiro = 7, rubino = 14, topazio = 12, smeraldo = 10, TOT = 43 +Collana massima di lunghezza 42 +TEST #8 +zaffiro = 13, rubino = 20, topazio = 12, smeraldo = 17, TOT = 62 +Collana massima di lunghezza 55 +TEST #9 +zaffiro = 17, rubino = 18, topazio = 6, smeraldo = 9, TOT = 50 +Collana massima di lunghezza 39 +TEST #10 +zaffiro = 5, rubino = 5, topazio = 15, smeraldo = 19, TOT = 44 +Collana massima di lunghezza 35 +TEST #11 +zaffiro = 18, rubino = 12, topazio = 20, smeraldo = 17, TOT = 67 +Collana massima di lunghezza 60 +TEST #12 +zaffiro = 13, rubino = 6, topazio = 19, smeraldo = 6, TOT = 44 +Collana massima di lunghezza 32 +TEST #13 +zaffiro = 17, rubino = 20, topazio = 15, smeraldo = 19, TOT = 71 +Collana massima di lunghezza 67 +TEST #14 +zaffiro = 12, rubino = 18, topazio = 17, smeraldo = 8, TOT = 55 +Collana massima di lunghezza 55 +TEST #15 +zaffiro = 7, rubino = 20, topazio = 12, smeraldo = 7, TOT = 46 +Collana massima di lunghezza 39 diff --git a/Laboratorio 6/Esercizio 2/main.c b/Laboratorio 6/Esercizio 2/main.c new file mode 100644 index 0000000..d418ea0 --- /dev/null +++ b/Laboratorio 6/Esercizio 2/main.c @@ -0,0 +1,201 @@ +// Laboratorio 6 - Esercizio 2 +// Matteo Schiff - s295565 + +#include +#include + +int fZ(int z, int r, int t, int s, int len); +int fR(int z, int r, int t, int s, int len); +int fS(int z, int r, int t, int s, int len); +int fT(int z, int r, int t, int s, int len); + +enum Pietra{zaffiro, rubino, topazio, smeraldo}; + +int *cache; +int mz, mr, mt, ms; + +// Funzioni helper per semplificare la memorizzazione +// NOTA se `getCache` restituisce 0 vuol dire che la collana non è ancora stata analizzata +int getCache(int p, int z, int r, int t, int s) { + return *(cache + p*mz*mr*mt*ms + z*mr*mt*ms + r*mt*ms + t*ms + s); +} + +void saveCache(int p, int z, int r, int t, int s, int val) { + *(cache + p*mz*mr*mt*ms + z*mr*mt*ms + r*mt*ms + t*ms + s) = val; +} + +int fZ(int z, int r, int t, int s, int len) { + if (len != 0 && getCache(zaffiro, z,r,t,s) != 0) { + return getCache(zaffiro,z,r,t,s); + } + + int x = -1; + int m; + if (z > 0) { + m = fZ(z-1,r,t,s,len +1); + if (m > x) + x = m; + } + + if (r > 0) { + m = fR(z,r-1,t,s,len +1); + if (m > x) + x = m; + } + + // se non è possibile più aggiungere pietre, ho raggiunto la lunghezza massima ottenibile dal ramo + if (x == -1) { + saveCache(zaffiro,z,r,t,s,len); + return len; + } + + // se no restituisco il massimo fin'ora + saveCache(zaffiro,z,r,t,s,x); + return x; +} + +int fR(int z, int r, int t, int s, int len) { + if (len != 0 && getCache(rubino, z,r,t,s) != 0) { + return getCache(rubino,z,r,t,s); + } + + int x = -1; + int m; + if (s > 0) { + m = fS(z,r,t,s-1,len +1); + if (m > x) + x = m; + } + + if (t > 0) { + m = fT(z,r,t-1,s,len +1); + if (m > x) + x = m; + } + + // se non è possibile più aggiungere pietre, ho raggiunto la lunghezza massima ottenibile dal ramo + if (x == -1) { + saveCache(rubino,z,r,t,s,len); + return len; + } + + // se no restituisco il massimo fin'ora + saveCache(rubino,z,r,t,s,x); + return x; +} + +int fT(int z, int r, int t, int s, int len) { + if (len != 0 && getCache(topazio, z,r,t,s) != 0) { + return getCache(topazio,z,r,t,s); + } + + int x = -1; + int m; + if (z > 0) { + m = fZ(z-1,r,t,s,len +1); + if (m > x) + x = m; + } + + if (r > 0) { + m = fR(z,r-1,t,s,len +1); + if (m > x) + x = m; + } + + // se non è possibile più aggiungere pietre, ho raggiunto la lunghezza massima ottenibile dal ramo + if (x == -1) { + saveCache(topazio,z,r,t,s,len); + return len; + } + + // se no restituisco il massimo fin'ora + saveCache(topazio,z,r,t,s,x); + return x; +} + +int fS(int z, int r, int t, int s, int len) { + if (len != 0 && getCache(smeraldo, z,r,t,s) != 0) { + return getCache(smeraldo,z,r,t,s); + } + + int x = -1; + int m; + if (s > 0) { + m = fS(z,r,t,s-1,len +1); + if (m > x) + x = m; + } + + if (t > 0) { + m = fT(z,r,t-1,s,len +1); + if (m > x) + x = m; + } + + // se non è possibile più aggiungere pietre, ho raggiunto la lunghezza massima ottenibile dal ramo + if (x == -1) { + saveCache(smeraldo,z,r,t,s,len); + return len; + } + + // se no restituisco il massimo fin'ora + saveCache(smeraldo,z,r,t,s,x); + return x; +} + +void solveCase(int z, int r, int t, int s) { + mz = z+1; + mr = r+1; + mt = t+1; + ms = s+1; + cache = calloc(4*mz*mr*mt*ms, sizeof(int)); + + int max = z+r+t+s; + + int res = -1, x; + + printf("zaffiri = %d, rubini = %d, topazi = %d, smeraldi = %d; numero pietre = %d\n", z,r,t,s,max); + + x = fZ(z-1,r,t,s,1); + if (x > res) + res = x; + + x = fR(z,r-1,t,s,1); + if (x > res) + res = x; + + x = fS(z,r,t,s-1,1); + if (x > res) + res = x; + + x = fT(z,r,t-1,s,1); + if (x > res) + res = x; + free(cache); + + printf("Collana massima di lunghezza %d\n", res); + fflush(stdout); +} + +int main() { + int z, r, t, s, N = 0; + + FILE *fp; + + if ((fp = fopen("hard_test_set.txt", "r")) == NULL) + { + puts("Impossibile aprire il file"); + return 1; + } + + fscanf(fp, "%d", &N); + + for (int i = 0; i < N; i++) { + fscanf(fp, " %d %d %d %d", &z, &r, &t, &s); + printf("Test case %d\n", i+1); + solveCase(z,r,t,s); + } + + fclose(fp); +} \ No newline at end of file diff --git a/Laboratorio 6/Esercizio 3/equipArray.c b/Laboratorio 6/Esercizio 3/equipArray.c new file mode 100644 index 0000000..7a9b4fc --- /dev/null +++ b/Laboratorio 6/Esercizio 3/equipArray.c @@ -0,0 +1,108 @@ +// Laboratorio 6 - Esercizio 3 - equipArray.c +// Matteo Schiff - s295565 + +#ifndef EQUIPARRAY_C_DEFINED +#define EQUIPARRAY_C_DEFINED + +#include +#include +#include + +#include "invArray.h" +#include "equipArray.h" +#include "inv.h" + +/* ADT di prima classe collezione di oggetti di equipaggiamento */ +typedef struct equipArray_s { + int inUse; + inv_t *items[EQUIP_SLOT]; +} *equipArray_t; + +/* creatore e disruttore */ +equipArray_t equipArray_init() { + equipArray_t new = malloc(sizeof(struct equipArray_s)); + new->inUse = 0; + return new; +} +void equipArray_free(equipArray_t equipArray) { + free(equipArray); +} + +/* quanti equipaggiamenti sono in uso */ +int equipArray_inUse(equipArray_t equipArray) { + return equipArray->inUse; +} + +void equipArray_apply_modifier(stat_t *stats, equipArray_t equipArray) { + for (int i = 0; i < equipArray_inUse(equipArray); i++) { + stat_sum(stats, &equipArray->items[i]->stat); + } +} + +/* scrittura su file */ +void equipArray_print(FILE *fp, equipArray_t equipArray, invArray_t invArray) { + for (int i = 0; i < equipArray->inUse; i++) { + printf(" %d: ", i); + inv_print(fp, equipArray->items[i]); + } +} + +void equipArray_insert(equipArray_t equipArray, invArray_t invArray) { + char name[LEN+1]; + + if (equipArray->inUse >= EQUIP_SLOT) { + puts("Tutti gli slot sono occupati"); + return; + } + + puts("Inserisci il nome dell'oggetto da equipaggiare: "); + scanf(" %50s", name); + int index = invArray_searchByName(invArray, name); + + if (index == -1) { + puts("Oggetto non trovato"); + return; + } + + inv_t *selected = invArray_getByIndex(invArray, index); + + equipArray->items[(equipArray->inUse)++] = selected; +} + +void equipArray_remove(equipArray_t equipArray, invArray_t invArray) { + int index; + + if (equipArray->inUse <= 0) { + puts("Tutti gli slot sono vuoti"); + return; + } + + puts("Oggetti equipaggiati: "); + equipArray_print(stdout, equipArray, invArray); + + puts("Inserisci l'indice dell'oggetto da rimuovere: "); + scanf(" %d", &index); + if (index < 0 || index >= equipArray->inUse) { + puts("Indice oggetto non valido"); + return; + } + + equipArray->items[index] = equipArray->items[--(equipArray->inUse)]; +} + +/* modifica equipaggiamento scegliendo un oggetto da inventario */ +void equipArray_update(equipArray_t equipArray, invArray_t invArray) { + char selection; + puts("Vuoi inserire o rimuovere un oggetto? Rispondi (i) o (r): "); + scanf(" %c", &selection); + + if (selection == 'i') { + equipArray_insert(equipArray, invArray); + } else { + equipArray_remove(equipArray, invArray); + } +} + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 6/Esercizio 3/equipArray.h b/Laboratorio 6/Esercizio 3/equipArray.h new file mode 100644 index 0000000..f34a25f --- /dev/null +++ b/Laboratorio 6/Esercizio 3/equipArray.h @@ -0,0 +1,34 @@ +// Laboratorio 6 - Esercizio 3 - equipArray.h +// Matteo Schiff - s295565 + +#ifndef EQUIPARRAY_H_DEFINED +#define EQUIPARRAY_H_DEFINED + +#include +#include +#include + +#define EQUIP_SLOT 8 + +#include "invArray.h" + +/* ADT di prima classe collezione di oggetti di equipaggiamento */ +typedef struct equipArray_s *equipArray_t; + +/* creatore e disruttore */ +equipArray_t equipArray_init(); +void equipArray_free(equipArray_t equipArray); + +/* quanti equipaggiamenti sono in uso */ +int equipArray_inUse(equipArray_t equipArray); + +void equipArray_apply_modifier(stat_t *stats, equipArray_t equipArray); + +/* scrittura su file */ +void equipArray_print(FILE *fp, equipArray_t equipArray, invArray_t invArray); +/* modifica equipaggiamento scegliendo un oggetto da inventario */ +void equipArray_update(equipArray_t equipArray, invArray_t invArray); + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 6/Esercizio 3/gdr.c b/Laboratorio 6/Esercizio 3/gdr.c new file mode 100644 index 0000000..c8cb4a2 --- /dev/null +++ b/Laboratorio 6/Esercizio 3/gdr.c @@ -0,0 +1,122 @@ +// Laboratorio 6 - Esercizio 3 - gdr.c +// Matteo Schiff - s295565 + +#include +#include +#include + +#include "pgList.h" +#include "invArray.h" +#include "pg.h" + +#define N_SCELTE 7 +#define DBG 0 + +enum { falso, vero }; +typedef int bool; + +void stampaMenu(char *scelte[], int *selezione){ + int i=0; + printf("\nMENU'\n"); + for(i=0;i %s\n",i,scelte[i]); + scanf(" %d",selezione); +} + +int main(int argc, char **argv) { + char *scelte[] = { + "Uscita", + "Stampa personaggi", + "Stampa inventario", + "Cerca personaggio", + "Aggiungi personaggio", + "Elimina personaggio", + "Modifica equip" + }; + + char codiceRicerca[LEN]; + int selezione; + FILE *fin; + bool fineProgramma; + + pgList_t pgList = pgList_init(); + invArray_t invArray = invArray_init(); + pg_t *pgp, pg; + + fin = fopen("pg.txt","r"); + pgList_read(fin, pgList); + fclose(fin); +#if DBG + pgList_print(stdout, pgList); +#endif /* DBG */ + + fin = fopen("inventario.txt","r"); + invArray_read(fin, invArray); + fclose(fin); +#if DBG + invArray_print(stdout, invArray); +#endif /* DBG */ + + fineProgramma = falso; + + do { + stampaMenu(scelte, &selezione); + switch(selezione){ + + case 0: { + fineProgramma = vero; + } break; + + case 1: { + pgList_print(stdout, pgList, invArray); + } break; + + case 2: { + invArray_print(stdout, invArray); + } break; + + case 3: { + printf("Inserire codice personaggio: "); + scanf("%s", codiceRicerca); + pgp = pgList_searchByCode(pgList, codiceRicerca); + if (pgp!=NULL) { + pg_print(stdout, pgp, invArray); + } else { + puts("Personaggio non trovato"); + } + } break; + + case 4: { + printf("Cod Nome Classe HP MP ATK DEF MAG SPR: "); + if (pg_read(stdin, &pg) != 0) { + pgList_insert(pgList, pg); + } + } break; + + case 5: { + printf("Inserire codice personaggio: "); + scanf("%s", codiceRicerca); + pgList_remove(pgList, codiceRicerca); + } break; + + case 6: { + printf("Inserire codice personaggio: "); + scanf("%s", codiceRicerca); + pgp = pgList_searchByCode(pgList, codiceRicerca); + if (pgp!=NULL) { + pg_updateEquip(pgp, invArray); + } else { + puts("Personaggio non trovato"); + } + } break; + + default:{ + printf("Scelta non valida\n"); + } break; + } + } while(!fineProgramma); + + pgList_free(pgList); + + return 0; +} diff --git a/Laboratorio 6/Esercizio 3/inv.c b/Laboratorio 6/Esercizio 3/inv.c new file mode 100644 index 0000000..a0c45ab --- /dev/null +++ b/Laboratorio 6/Esercizio 3/inv.c @@ -0,0 +1,71 @@ +// Laboratorio 6 - Esercizio 3 - inv.c +// Matteo Schiff - s295565 + +#ifndef INV_C_DEFINED +#define INV_C_DEFINED + +#include +#include +#include + +#include +#include "inv.h" + +/* funzioni di input/output delle statistiche */ +void stat_read(FILE *fp, stat_t *statp) { + fscanf(fp, " %d %d %d %d %d %d", &(statp->hp), &(statp->mp), &(statp->atk), &(statp->def), &(statp->mag), &(statp->spr)); +} + +int zero_se_soglia(int a, int soglia) { + if (a < soglia) + return 0; + return a; +} + +void stat_print(FILE *fp, stat_t *statp, int soglia) { + fprintf(fp, "HP: %d, MP: %d, ATK: %d, DEF: %d, MAG: %d, SPR: %d\n", + zero_se_soglia(statp->hp, soglia), + zero_se_soglia(statp->mp, soglia), + zero_se_soglia(statp->atk, soglia), + zero_se_soglia(statp->def, soglia), + zero_se_soglia(statp->mag, soglia), + zero_se_soglia(statp->spr, soglia)); +} + +void stat_copy(stat_t *a, stat_t *b) { + a->atk = b->atk; + a->def = b->def; + a->hp = b->hp; + a->mag = b->mag; + a->mp = b->mp; + a->spr = b->spr; +} + +void stat_sum(stat_t *a, stat_t *b) { + a->atk += b->atk; + a->def += b->def; + a->hp += b->hp; + a->mag += b->mag; + a->mp += b->mp; + a->spr += b->spr; +} + +/* funzioni di input/output di un oggetto dell'inventario */ +void inv_read(FILE *fp, inv_t *invp) { + fscanf(fp, " %49s %49s", invp->nome, invp->tipo); + stat_read(fp, &(invp->stat)); +} + +void inv_print(FILE *fp, inv_t *invp) { + fprintf(fp, " %s (%s) - ", invp->nome, invp->tipo); + stat_print(fp, &(invp->stat),INT_MIN); +} + +/* ritorna il campo stat di un oggetto dell'inventario */ +stat_t inv_getStat(inv_t *invp) { + return invp->stat; +} + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 6/Esercizio 3/inv.h b/Laboratorio 6/Esercizio 3/inv.h new file mode 100644 index 0000000..2d80ccf --- /dev/null +++ b/Laboratorio 6/Esercizio 3/inv.h @@ -0,0 +1,42 @@ +// Laboratorio 6 - Esercizio 3 - inv.h +// Matteo Schiff - s295565 + +#ifndef INV_H_DEFINED +#define INV_H_DEFINED + +#include +#include +#include + +#define LEN 50 +#define MIN_STAT 1 + +/* quasi ADT statistiche */ +typedef struct stat_s { + int hp, mp, atk, def, mag, spr; +} stat_t; + +/* quasi ADT oggetto di inventario */ +typedef struct inv_s { + char nome[LEN]; + char tipo[LEN]; + stat_t stat; +} inv_t; + +/* funzioni di input/output delle statistiche */ +void stat_read(FILE *fp, stat_t *statp); +void stat_print(FILE *fp, stat_t *statp, int soglia); + +void stat_copy(stat_t *a, stat_t *b); +void stat_sum(stat_t *a, stat_t *b); + +/* funzioni di input/output di un oggetto dell'inventario */ +void inv_read(FILE *fp, inv_t *invp); +void inv_print(FILE *fp, inv_t *invp); + +/* ritorna il campo stat di un oggetto dell'inventario */ +stat_t inv_getStat(inv_t *invp); + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 6/Esercizio 3/invArray.c b/Laboratorio 6/Esercizio 3/invArray.c new file mode 100644 index 0000000..358b63b --- /dev/null +++ b/Laboratorio 6/Esercizio 3/invArray.c @@ -0,0 +1,67 @@ +// Laboratorio 6 - Esercizio 3 - invArray.c +// Matteo Schiff - s295565 + +#ifndef INVARRAY_C_DEFINED +#define INVARRAY_C_DEFINED + +#include +#include +#include + +#include "inv.h" + +typedef struct invArray_s { + int N; + inv_t *array; +} *invArray_t; + +/* creatore e disruttore */ +invArray_t invArray_init() { + invArray_t new = malloc(sizeof(struct invArray_s)); + new->N = 0; + new->array = NULL; + return new; +} + +void invArray_free(invArray_t invArray) { + free(invArray->array); + free(invArray); +} + +/* lettura e scrittura su file */ +void invArray_read(FILE *fp, invArray_t invArray) { + if (fscanf(fp, " %d", &invArray->N) != 1) + return; + + invArray->array = malloc(invArray->N * sizeof(inv_t)); + + for (int i = 0; i < invArray->N; i++) { + inv_read(fp, &invArray->array[i]); + } +} +void invArray_print(FILE *fp, invArray_t invArray) { + for (int i = 0; i < invArray->N; i++) { + inv_print(fp, &invArray->array[i]); + } +} + +/* ritorna puntatore a oggetto selezionato da indice (nel vettore) */ +inv_t *invArray_getByIndex(invArray_t invArray, int index) { + if (index >= invArray->N) + return NULL; + + return &(invArray->array[index]); +} +/* ritorna indice (nel vettore) a oggetto selezionato da nome */ +int invArray_searchByName(invArray_t invArray, char *name) { + for (int i = 0; i < invArray->N; i++) { + if (!strcmp(invArray->array[i].nome, name)) + return i; + } + + return -1; +} + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 6/Esercizio 3/invArray.h b/Laboratorio 6/Esercizio 3/invArray.h new file mode 100644 index 0000000..4eb1fd7 --- /dev/null +++ b/Laboratorio 6/Esercizio 3/invArray.h @@ -0,0 +1,30 @@ +// Laboratorio 6 - Esercizio 3 - invArray.h +// Matteo Schiff - s295565 + +#ifndef INVARRAY_H_DEFINED +#define INVARRAY_H_DEFINED + +#include +#include +#include + +#include "inv.h" + +/* ADT di prima classe collezione di oggetti di inventario */ +typedef struct invArray_s *invArray_t; + +/* creatore e disruttore */ +invArray_t invArray_init(); +void invArray_free(invArray_t invArray); + +/* lettura e scrittura su file */ +void invArray_read(FILE *fp, invArray_t invArray); +void invArray_print(FILE *fp, invArray_t invArray); +/* ritorna puntatore a oggetto selezionato da indice (nel vettore) */ +inv_t *invArray_getByIndex(invArray_t invArray, int index); +/* ritorna indice (nel vettore) a oggetto selezionato da nome */ +int invArray_searchByName(invArray_t invArray, char *name); + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 6/Esercizio 3/inventario.txt b/Laboratorio 6/Esercizio 3/inventario.txt new file mode 100644 index 0000000..e91357e --- /dev/null +++ b/Laboratorio 6/Esercizio 3/inventario.txt @@ -0,0 +1,16 @@ +15 +Excalibur Spada2M 0 0 120 0 0 50 +Filatterio Accessorio -100 20 -30 -30 25 25 +ArmillaDiDiamante Accessorio 0 0 25 0 25 +Escutcheon Scudo 1000 50 0 75 0 0 +MantoElfico Vesti 0 50 0 10 10 10 +Pendragon Scudo 250 0 0 45 0 30 +Oricalco Reliquia 0 0 0 0 15 15 +TalismanoNero Accessorio -500 150 0 0 100 50 +AmmazzaDraghi Spada2M 0 0 80 -20 0 -20 +Fiocco Accessorio 0 0 1 1 1 1 +CorazzaAdamantina ArmaturaPesante 3333 333 -15 33 -15 33 +DagaRunica Pugnale 0 50 10 0 35 0 +Tempesta Spada1M 0 0 40 0 -5 0 +Maximillian ArmaturaLeggera 500 0 0 30 0 15 +Ametista Reliquia 0 0 15 15 0 0 \ No newline at end of file diff --git a/Laboratorio 6/Esercizio 3/pg.c b/Laboratorio 6/Esercizio 3/pg.c new file mode 100644 index 0000000..dd521dc --- /dev/null +++ b/Laboratorio 6/Esercizio 3/pg.c @@ -0,0 +1,49 @@ +// Laboratorio 6 - Esercizio 3 - pg.c +// Matteo Schiff - s295565 + +#ifndef PG_C_DEFINED +#define PG_C_DEFINED + +#include +#include +#include + +#include "equipArray.h" +#include "pg.h" + +void pg_calc_stats(pg_t *pgp) { + stat_copy(&pgp->eq_stat, &pgp->b_stat); + equipArray_apply_modifier(&pgp->eq_stat, pgp->equip); +} + +/* lettura e scrittura su file */ +int pg_read(FILE *fp, pg_t *pgp) { + if (fscanf(fp, " %49s %49s %49s", pgp->cod, pgp->nome, pgp->classe) != 3) + return 0; + + stat_read(fp, &(pgp->b_stat)); + pgp->equip = equipArray_init(); + pg_calc_stats(pgp); + + return 1; +} +/* non essendo struct dinamica, pulisce chiamando il distruttore di equipArray */ +void pg_clean(pg_t *pgp) { + free(pgp->equip); +} + +void pg_print(FILE *fp, pg_t *pgp, invArray_t invArray) { + fprintf(fp, "%s (%s)\n Classe: %s\n Statistiche - ", pgp->nome, pgp->cod, pgp->classe); + stat_print(fp, &(pgp->eq_stat), 0); + equipArray_print(fp, pgp->equip, invArray); +} +/* modifica personaggio aggiungendo/togliendo un equipaggiamento selezionato da inventario: +di fatto e' sufficiente chiamare l'opportuna funzione dal modulo equipArray */ +void pg_updateEquip(pg_t *pgp, invArray_t invArray) { + equipArray_update(pgp->equip, invArray); + pg_calc_stats(pgp); +} + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 6/Esercizio 3/pg.h b/Laboratorio 6/Esercizio 3/pg.h new file mode 100644 index 0000000..13cb122 --- /dev/null +++ b/Laboratorio 6/Esercizio 3/pg.h @@ -0,0 +1,35 @@ +// Laboratorio 6 - Esercizio 3 - pg.h +// Matteo Schiff - s295565 + +#ifndef PG_H_DEFINED +#define PG_H_DEFINED + +#include +#include +#include + +#include "equipArray.h" + +/* quasi ADT personaggio; si noti che si tratta di un composto con riferimento +a un equipArray di proprieta' */ +typedef struct pg_s { + char cod[LEN]; + char nome[LEN]; + char classe[LEN]; + stat_t b_stat, eq_stat; + equipArray_t equip; +} pg_t; + +/* lettura e scrittura su file */ +int pg_read(FILE *fp, pg_t *pgp); +/* non essendo struct dinamica, pulisce chiamando il distruttire di equipArray */ +void pg_clean(pg_t *pgp); + +void pg_print(FILE *fp, pg_t *pgp, invArray_t invArray); +/* modifica personaggio aggiungendo/togliendo un equipaggiamento selezionato da inventario: +di fatto e' sufficiente chiamare l'opportuna funzione dal modulo equipArray */ +void pg_updateEquip(pg_t *pgp, invArray_t invArray); + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 6/Esercizio 3/pg.txt b/Laboratorio 6/Esercizio 3/pg.txt new file mode 100644 index 0000000..049852c --- /dev/null +++ b/Laboratorio 6/Esercizio 3/pg.txt @@ -0,0 +1,10 @@ +PG0001 Sephiroth Guerriero 1832 71 116 65 41 49 +PG0002 Aerith MagoBianco 976 144 12 39 121 140 +PG0003 Vivi MagoNero 1001 136 17 36 131 115 +PG0004 Beatrix Templare 1654 99 85 35 70 61 +PG0005 Orlandeau Paladino 1701 84 81 68 34 48 +PG0006 Basch Capitano 2199 46 32 98 33 89 +PG0007 Lulu MagoNero 999 139 21 33 119 117 +PG0008 Yuna Evocatrice 1019 100 32 17 97 99 +PG0009 DarkCecil CavaliereNero 1901 48 106 90 12 18 +PG0010 Kefka Arcimago 1271 89 39 47 89 64 diff --git a/Laboratorio 6/Esercizio 3/pgList.c b/Laboratorio 6/Esercizio 3/pgList.c new file mode 100644 index 0000000..6f8d620 --- /dev/null +++ b/Laboratorio 6/Esercizio 3/pgList.c @@ -0,0 +1,131 @@ +// Laboratorio 6 - Esercizio 3 - pgList.c +// Matteo Schiff - s295565 + +#ifndef PGLIST_C_DEFINED +#define PGLIST_C_DEFINED + +#include +#include +#include + +#include "pgList.h" + +typedef struct node_s *link; + +typedef struct node_s { + pg_t val; + link next; +} node; + +/* ADT di prima classe collezione di personaggi */ +typedef struct pgList_s { + link head; + link tail; + int nPg; +} *pgList_t; + +link new_node(pg_t val, link next) { + link t = malloc(sizeof(node)); + if (t == NULL) { + printf("ERROR: out of memory"); + exit(2); + } + t->val = val; + t->next = next; + + return t; +} + +void free_node(link p) { + pg_clean(&p->val); + free(p); +} + +/* creatore e distruttore */ +pgList_t pgList_init() { + pgList_t new = malloc(sizeof(struct pgList_s)); + new->head = NULL; + new->tail = NULL; + new->nPg = 0; + return new; +} + +void pgList_free(pgList_t pgList) { + link p, x; + for (p = pgList->head, x = pgList->head->next; x != NULL; p = x, x = x->next){ + free_node(p); + } + free(pgList); +} + +/* lettura e scrittura su file */ +void pgList_read(FILE *fp, pgList_t pgList) { + while (!feof(fp)) + { + pg_t pgp; + if (pg_read(fp, &pgp) != 0) { + pgList_insert(pgList, pgp); + } + } +} + +void pgList_print(FILE *fp, pgList_t pgList, invArray_t invArray) { + link p; + + for (p = pgList->head; p != NULL; p = p->next) { + pg_print(fp, &(p->val), invArray); + } +} + +/* inserimento di un nuovo personaggio */ +void pgList_insert(pgList_t pgList, pg_t pg) { + link new = new_node(pg, NULL); + if (pgList->head == NULL) { + pgList->head = new; + } else { + pgList->tail->next = new; + } + + pgList->tail = new; +} +/* cancellazione con rimozione */ +void pgList_remove(pgList_t pgList, char* cod) { + link p, x; + + if (pgList->head == NULL) + return; + + for (x = pgList->head, p = NULL; x != NULL; p = x, x = x->next) { + if (!strcmp(x->val.cod, cod)) { + if (p == NULL) { + pgList->head = x->next; + } else { + p->next = x->next; + + // se tolgo l'ultimo elemento devo aggiornare `tail` + if (x->next == NULL) + pgList->tail = p; + } + + free_node(x); + break; + } + } +} + +/* ricerca per codice, ritornando il puntatore */ +pg_t *pgList_searchByCode(pgList_t pgList, char* cod) { + link p; + + for (p = pgList->head; p != NULL; p = p->next) { + if (!strcmp(p->val.cod, cod)) { + return &(p->val); + } + } + + return NULL; +} + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 6/Esercizio 3/pgList.h b/Laboratorio 6/Esercizio 3/pgList.h new file mode 100644 index 0000000..dd2317a --- /dev/null +++ b/Laboratorio 6/Esercizio 3/pgList.h @@ -0,0 +1,33 @@ +// Laboratorio 6 - Esercizio 3 - pgList.h +// Matteo Schiff - s295565 + +#ifndef PGLIST_H_DEFINED +#define PGLIST_H_DEFINED + +#include +#include +#include + +#include "pg.h" + +/* ADT di prima classe collezione di personaggi */ +typedef struct pgList_s *pgList_t; + +/* creatore e distruttore */ +pgList_t pgList_init(); +void pgList_free(pgList_t pgList); + +/* lettura e scrittura su file */ +void pgList_read(FILE *fp, pgList_t pgList); +void pgList_print(FILE *fp, pgList_t pgList, invArray_t invArray); + +/* inserimento di un nuovo personaggio */ +void pgList_insert(pgList_t pgList, pg_t pg); +/* cancellazione con rimozione */ +void pgList_remove(pgList_t pgList, char* cod); +/* ricerca per codice, ritornando il puntatore */ +pg_t *pgList_searchByCode(pgList_t pgList, char* cod); + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 7/Esercizio 1/equipArray.c b/Laboratorio 7/Esercizio 1/equipArray.c new file mode 100644 index 0000000..157ccda --- /dev/null +++ b/Laboratorio 7/Esercizio 1/equipArray.c @@ -0,0 +1,103 @@ +// Laboratorio 7 - Esercizio 1 - equipArray.c +// Matteo Schiff - s295565 + +#ifndef EQUIPARRAY_C_DEFINED +#define EQUIPARRAY_C_DEFINED + +#include +#include +#include + +#include "invArray.h" +#include "equipArray.h" + +/* ADT di prima classe collezione di oggetti di equipaggiamento */ +typedef struct equipArray_s { + int inUse; + int items[EQUIP_SLOT]; +} *equipArray_t; + +/* creatore e disruttore */ +equipArray_t equipArray_init() { + equipArray_t new = malloc(sizeof(struct equipArray_s)); + new->inUse = 0; + return new; +} +void equipArray_free(equipArray_t equipArray) { + free(equipArray); +} + +/* quanti equipaggiamenti sono in uso */ +int equipArray_inUse(equipArray_t equipArray) { + return equipArray->inUse; +} + +int equipArray_getEquipByIndex(equipArray_t equipArray, int index) { + return equipArray->items[index]; +} + +/* scrittura su file */ +void equipArray_print(FILE *fp, equipArray_t equipArray, invArray_t invArray) { + for (int i = 0; i < equipArray->inUse; i++) { + printf(" %d: ", i); + invArray_printByIndex(fp, invArray, equipArray->items[i]); + } +} + +void equipArray_insert(equipArray_t equipArray, invArray_t invArray) { + char name[LEN+1]; + + if (equipArray->inUse >= EQUIP_SLOT) { + puts("Tutti gli slot sono occupati"); + return; + } + + puts("Inserisci il nome dell'oggetto da equipaggiare: "); + scanf(" %50s", name); + int index = invArray_searchByName(invArray, name); + + if (index == -1) { + puts("Oggetto non trovato"); + return; + } + + equipArray->items[(equipArray->inUse)++] = index; +} + +void equipArray_remove(equipArray_t equipArray, invArray_t invArray) { + int index; + + if (equipArray->inUse <= 0) { + puts("Tutti gli slot sono vuoti"); + return; + } + + puts("Oggetti equipaggiati: "); + equipArray_print(stdout, equipArray, invArray); + + puts("Inserisci l'indice dell'oggetto da rimuovere: "); + scanf(" %d", &index); + if (index < 0 || index >= equipArray->inUse) { + puts("Indice oggetto non valido"); + return; + } + + equipArray->items[index] = equipArray->items[--(equipArray->inUse)]; +} + +/* modifica equipaggiamento scegliendo un oggetto da inventario */ +void equipArray_update(equipArray_t equipArray, invArray_t invArray) { + char selection; + puts("Vuoi inserire o rimuovere un oggetto? Rispondi (i) o (r): "); + scanf(" %c", &selection); + + if (selection == 'i') { + equipArray_insert(equipArray, invArray); + } else { + equipArray_remove(equipArray, invArray); + } +} + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 7/Esercizio 1/equipArray.h b/Laboratorio 7/Esercizio 1/equipArray.h new file mode 100644 index 0000000..7d332d4 --- /dev/null +++ b/Laboratorio 7/Esercizio 1/equipArray.h @@ -0,0 +1,33 @@ +// Laboratorio 7 - Esercizio 1 - equipArray.h +// Matteo Schiff - s295565 + +#ifndef EQUIPARRAY_H_DEFINED +#define EQUIPARRAY_H_DEFINED + +#include +#include +#include + +#define EQUIP_SLOT 8 + +#include "invArray.h" + +/* ADT di prima classe collezione di oggetti di equipaggiamento */ +typedef struct equipArray_s *equipArray_t; + +/* creatore e disruttore */ +equipArray_t equipArray_init(); +void equipArray_free(equipArray_t equipArray); + +/* quanti equipaggiamenti sono in uso */ +int equipArray_inUse(equipArray_t equipArray); + +/* scrittura su file */ +void equipArray_print(FILE *fp, equipArray_t equipArray, invArray_t invArray); +/* modifica equipaggiamento scegliendo un oggetto da inventario */ +void equipArray_update(equipArray_t equipArray, invArray_t invArray); +int equipArray_getEquipByIndex(equipArray_t equipArray, int index); + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 7/Esercizio 1/gdr.c b/Laboratorio 7/Esercizio 1/gdr.c new file mode 100644 index 0000000..ee12466 --- /dev/null +++ b/Laboratorio 7/Esercizio 1/gdr.c @@ -0,0 +1,122 @@ +// Laboratorio 7 - Esercizio 1 - gdr.c +// Matteo Schiff - s295565 + +#include +#include +#include + +#include "pgList.h" +#include "invArray.h" +#include "pg.h" + +#define N_SCELTE 7 +#define DBG 0 + +enum { falso, vero }; +typedef int bool; + +void stampaMenu(char *scelte[], int *selezione){ + int i=0; + printf("\nMENU'\n"); + for(i=0;i %s\n",i,scelte[i]); + scanf(" %d",selezione); +} + +int main(int argc, char **argv) { + char *scelte[] = { + "Uscita", + "Stampa personaggi", + "Stampa inventario", + "Cerca personaggio", + "Aggiungi personaggio", + "Elimina personaggio", + "Modifica equip" + }; + + char codiceRicerca[LEN]; + int selezione; + FILE *fin; + bool fineProgramma; + + pgList_t pgList = pgList_init(); + invArray_t invArray = invArray_init(); + pg_t *pgp, pg; + + fin = fopen("pg.txt","r"); + pgList_read(fin, pgList); + fclose(fin); +#if DBG + pgList_print(stdout, pgList); +#endif /* DBG */ + + fin = fopen("inventario.txt","r"); + invArray_read(fin, invArray); + fclose(fin); +#if DBG + invArray_print(stdout, invArray); +#endif /* DBG */ + + fineProgramma = falso; + + do { + stampaMenu(scelte, &selezione); + switch(selezione){ + + case 0: { + fineProgramma = vero; + } break; + + case 1: { + pgList_print(stdout, pgList, invArray); + } break; + + case 2: { + invArray_print(stdout, invArray); + } break; + + case 3: { + printf("Inserire codice personaggio: "); + scanf("%s", codiceRicerca); + pgp = pgList_searchByCode(pgList, codiceRicerca); + if (pgp!=NULL) { + pg_print(stdout, pgp, invArray); + } else { + puts("Personaggio non trovato"); + } + } break; + + case 4: { + printf("Cod Nome Classe HP MP ATK DEF MAG SPR: "); + if (pg_read(stdin, &pg) != 0) { + pgList_insert(pgList, pg); + } + } break; + + case 5: { + printf("Inserire codice personaggio: "); + scanf("%s", codiceRicerca); + pgList_remove(pgList, codiceRicerca); + } break; + + case 6: { + printf("Inserire codice personaggio: "); + scanf("%s", codiceRicerca); + pgp = pgList_searchByCode(pgList, codiceRicerca); + if (pgp!=NULL) { + pg_updateEquip(pgp, invArray); + } else { + puts("Personaggio non trovato"); + } + } break; + + default:{ + printf("Scelta non valida\n"); + } break; + } + } while(!fineProgramma); + + pgList_free(pgList); + + return 0; +} diff --git a/Laboratorio 7/Esercizio 1/inv.c b/Laboratorio 7/Esercizio 1/inv.c new file mode 100644 index 0000000..2e0f4dc --- /dev/null +++ b/Laboratorio 7/Esercizio 1/inv.c @@ -0,0 +1,71 @@ +// Laboratorio 7 - Esercizio 1 - inv.c +// Matteo Schiff - s295565 + +#ifndef INV_C_DEFINED +#define INV_C_DEFINED + +#include +#include +#include + +#include +#include "inv.h" + +/* funzioni di input/output delle statistiche */ +void stat_read(FILE *fp, stat_t *statp) { + fscanf(fp, " %d %d %d %d %d %d", &(statp->hp), &(statp->mp), &(statp->atk), &(statp->def), &(statp->mag), &(statp->spr)); +} + +int zero_se_soglia(int a, int soglia) { + if (a < soglia) + return 0; + return a; +} + +void stat_print(FILE *fp, stat_t *statp, int soglia) { + fprintf(fp, "HP: %d, MP: %d, ATK: %d, DEF: %d, MAG: %d, SPR: %d\n", + zero_se_soglia(statp->hp, soglia), + zero_se_soglia(statp->mp, soglia), + zero_se_soglia(statp->atk, soglia), + zero_se_soglia(statp->def, soglia), + zero_se_soglia(statp->mag, soglia), + zero_se_soglia(statp->spr, soglia)); +} + +void stat_copy(stat_t *a, stat_t *b) { + a->atk = b->atk; + a->def = b->def; + a->hp = b->hp; + a->mag = b->mag; + a->mp = b->mp; + a->spr = b->spr; +} + +void stat_sum(stat_t *a, stat_t *b) { + a->atk += b->atk; + a->def += b->def; + a->hp += b->hp; + a->mag += b->mag; + a->mp += b->mp; + a->spr += b->spr; +} + +/* funzioni di input/output di un oggetto dell'inventario */ +void inv_read(FILE *fp, inv_t *invp) { + fscanf(fp, " %49s %49s", invp->nome, invp->tipo); + stat_read(fp, &(invp->stat)); +} + +void inv_print(FILE *fp, inv_t *invp) { + fprintf(fp, " %s (%s) - ", invp->nome, invp->tipo); + stat_print(fp, &(invp->stat),INT_MIN); +} + +/* ritorna il campo stat di un oggetto dell'inventario */ +stat_t inv_getStat(inv_t *invp) { + return invp->stat; +} + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 7/Esercizio 1/inv.h b/Laboratorio 7/Esercizio 1/inv.h new file mode 100644 index 0000000..e880e5b --- /dev/null +++ b/Laboratorio 7/Esercizio 1/inv.h @@ -0,0 +1,42 @@ +// Laboratorio 7 - Esercizio 1 - inv.h +// Matteo Schiff - s295565 + +#ifndef INV_H_DEFINED +#define INV_H_DEFINED + +#include +#include +#include + +#define LEN 50 +#define MIN_STAT 1 + +/* quasi ADT statistiche */ +typedef struct stat_s { + int hp, mp, atk, def, mag, spr; +} stat_t; + +/* quasi ADT oggetto di inventario */ +typedef struct inv_s { + char nome[LEN]; + char tipo[LEN]; + stat_t stat; +} inv_t; + +/* funzioni di input/output delle statistiche */ +void stat_read(FILE *fp, stat_t *statp); +void stat_print(FILE *fp, stat_t *statp, int soglia); + +void stat_copy(stat_t *a, stat_t *b); +void stat_sum(stat_t *a, stat_t *b); + +/* funzioni di input/output di un oggetto dell'inventario */ +void inv_read(FILE *fp, inv_t *invp); +void inv_print(FILE *fp, inv_t *invp); + +/* ritorna il campo stat di un oggetto dell'inventario */ +stat_t inv_getStat(inv_t *invp); + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 7/Esercizio 1/invArray.c b/Laboratorio 7/Esercizio 1/invArray.c new file mode 100644 index 0000000..dc20374 --- /dev/null +++ b/Laboratorio 7/Esercizio 1/invArray.c @@ -0,0 +1,75 @@ +// Laboratorio 7 - Esercizio 1 - invArray.c +// Matteo Schiff - s295565 + +#ifndef INVARRAY_C_DEFINED +#define INVARRAY_C_DEFINED + +#include +#include +#include + +#include "inv.h" + +typedef struct invArray_s { + int N; + inv_t *array; +} *invArray_t; + +/* creatore e disruttore */ +invArray_t invArray_init() { + invArray_t new = malloc(sizeof(struct invArray_s)); + new->N = 0; + new->array = NULL; + return new; +} + +void invArray_free(invArray_t invArray) { + free(invArray->array); + free(invArray); +} + +/* lettura e scrittura su file */ +void invArray_read(FILE *fp, invArray_t invArray) { + if (fscanf(fp, " %d", &invArray->N) != 1) + return; + + invArray->array = malloc(invArray->N * sizeof(inv_t)); + + for (int i = 0; i < invArray->N; i++) { + inv_read(fp, &invArray->array[i]); + } +} +void invArray_print(FILE *fp, invArray_t invArray) { + for (int i = 0; i < invArray->N; i++) { + inv_print(fp, &invArray->array[i]); + } +} + +void invArray_printByIndex(FILE *fp, invArray_t invArray, int index) { + if (index >= invArray->N) + return; + + inv_print(fp, &invArray->array[index]); + +} + +/* ritorna puntatore a oggetto selezionato da indice (nel vettore) */ +inv_t *invArray_getByIndex(invArray_t invArray, int index) { + if (index >= invArray->N) + return NULL; + + return &(invArray->array[index]); +} +/* ritorna indice (nel vettore) a oggetto selezionato da nome */ +int invArray_searchByName(invArray_t invArray, char *name) { + for (int i = 0; i < invArray->N; i++) { + if (!strcmp(invArray->array[i].nome, name)) + return i; + } + + return -1; +} + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 7/Esercizio 1/invArray.h b/Laboratorio 7/Esercizio 1/invArray.h new file mode 100644 index 0000000..87e4949 --- /dev/null +++ b/Laboratorio 7/Esercizio 1/invArray.h @@ -0,0 +1,31 @@ +// Laboratorio 7 - Esercizio 1 - invArray.h +// Matteo Schiff - s295565 + +#ifndef INVARRAY_H_DEFINED +#define INVARRAY_H_DEFINED + +#include +#include +#include + +#include "inv.h" + +/* ADT di prima classe collezione di oggetti di inventario */ +typedef struct invArray_s *invArray_t; + +/* creatore e disruttore */ +invArray_t invArray_init(); +void invArray_free(invArray_t invArray); + +/* lettura e scrittura su file */ +void invArray_read(FILE *fp, invArray_t invArray); +void invArray_print(FILE *fp, invArray_t invArray); +/* ritorna puntatore a oggetto selezionato da indice (nel vettore) */ +void invArray_printByIndex(FILE *fp, invArray_t invArray, int index); +inv_t *invArray_getByIndex(invArray_t invArray, int index); +/* ritorna indice (nel vettore) a oggetto selezionato da nome */ +int invArray_searchByName(invArray_t invArray, char *name); + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 7/Esercizio 1/inventario.txt b/Laboratorio 7/Esercizio 1/inventario.txt new file mode 100644 index 0000000..e91357e --- /dev/null +++ b/Laboratorio 7/Esercizio 1/inventario.txt @@ -0,0 +1,16 @@ +15 +Excalibur Spada2M 0 0 120 0 0 50 +Filatterio Accessorio -100 20 -30 -30 25 25 +ArmillaDiDiamante Accessorio 0 0 25 0 25 +Escutcheon Scudo 1000 50 0 75 0 0 +MantoElfico Vesti 0 50 0 10 10 10 +Pendragon Scudo 250 0 0 45 0 30 +Oricalco Reliquia 0 0 0 0 15 15 +TalismanoNero Accessorio -500 150 0 0 100 50 +AmmazzaDraghi Spada2M 0 0 80 -20 0 -20 +Fiocco Accessorio 0 0 1 1 1 1 +CorazzaAdamantina ArmaturaPesante 3333 333 -15 33 -15 33 +DagaRunica Pugnale 0 50 10 0 35 0 +Tempesta Spada1M 0 0 40 0 -5 0 +Maximillian ArmaturaLeggera 500 0 0 30 0 15 +Ametista Reliquia 0 0 15 15 0 0 \ No newline at end of file diff --git a/Laboratorio 7/Esercizio 1/pg.c b/Laboratorio 7/Esercizio 1/pg.c new file mode 100644 index 0000000..d51b89e --- /dev/null +++ b/Laboratorio 7/Esercizio 1/pg.c @@ -0,0 +1,58 @@ +// Laboratorio 7 - Esercizio 1 - pg.c +// Matteo Schiff - s295565 + +#ifndef PG_C_DEFINED +#define PG_C_DEFINED + +#include +#include +#include + +#include "equipArray.h" +#include "pg.h" + +void pg_calc_stats(pg_t *pgp, invArray_t invArray) +{ + stat_copy(&pgp->eq_stat, &pgp->b_stat); + for (int i = 0; i < equipArray_inUse(pgp->equip); i++) { + int index = equipArray_getEquipByIndex(pgp->equip, i); + inv_t *item = invArray_getByIndex(invArray, index); + stat_sum(&pgp->eq_stat, &item->stat); + } +} + +/* lettura e scrittura su file */ +int pg_read(FILE *fp, pg_t *pgp) +{ + if (fscanf(fp, " %49s %49s %49s", pgp->cod, pgp->nome, pgp->classe) != 3) + return 0; + + stat_read(fp, &(pgp->b_stat)); + pgp->equip = equipArray_init(); + stat_copy(&pgp->eq_stat, &pgp->b_stat); + + return 1; +} +/* non essendo struct dinamica, pulisce chiamando il distruttore di equipArray */ +void pg_clean(pg_t *pgp) +{ + free(pgp->equip); +} + +void pg_print(FILE *fp, pg_t *pgp, invArray_t invArray) +{ + fprintf(fp, "%s (%s)\n Classe: %s\n Statistiche - ", pgp->nome, pgp->cod, pgp->classe); + stat_print(fp, &(pgp->eq_stat), 0); + equipArray_print(fp, pgp->equip, invArray); +} +/* modifica personaggio aggiungendo/togliendo un equipaggiamento selezionato da inventario: +di fatto e' sufficiente chiamare l'opportuna funzione dal modulo equipArray */ +void pg_updateEquip(pg_t *pgp, invArray_t invArray) +{ + equipArray_update(pgp->equip, invArray); + pg_calc_stats(pgp, invArray); +} + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 7/Esercizio 1/pg.h b/Laboratorio 7/Esercizio 1/pg.h new file mode 100644 index 0000000..3841966 --- /dev/null +++ b/Laboratorio 7/Esercizio 1/pg.h @@ -0,0 +1,35 @@ +// Laboratorio 7 - Esercizio 1 - pg.h +// Matteo Schiff - s295565 + +#ifndef PG_H_DEFINED +#define PG_H_DEFINED + +#include +#include +#include + +#include "equipArray.h" + +/* quasi ADT personaggio; si noti che si tratta di un composto con riferimento +a un equipArray di proprieta' */ +typedef struct pg_s { + char cod[LEN]; + char nome[LEN]; + char classe[LEN]; + stat_t b_stat, eq_stat; + equipArray_t equip; +} pg_t; + +/* lettura e scrittura su file */ +int pg_read(FILE *fp, pg_t *pgp); +/* non essendo struct dinamica, pulisce chiamando il distruttire di equipArray */ +void pg_clean(pg_t *pgp); + +void pg_print(FILE *fp, pg_t *pgp, invArray_t invArray); +/* modifica personaggio aggiungendo/togliendo un equipaggiamento selezionato da inventario: +di fatto e' sufficiente chiamare l'opportuna funzione dal modulo equipArray */ +void pg_updateEquip(pg_t *pgp, invArray_t invArray); + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 7/Esercizio 1/pg.txt b/Laboratorio 7/Esercizio 1/pg.txt new file mode 100644 index 0000000..049852c --- /dev/null +++ b/Laboratorio 7/Esercizio 1/pg.txt @@ -0,0 +1,10 @@ +PG0001 Sephiroth Guerriero 1832 71 116 65 41 49 +PG0002 Aerith MagoBianco 976 144 12 39 121 140 +PG0003 Vivi MagoNero 1001 136 17 36 131 115 +PG0004 Beatrix Templare 1654 99 85 35 70 61 +PG0005 Orlandeau Paladino 1701 84 81 68 34 48 +PG0006 Basch Capitano 2199 46 32 98 33 89 +PG0007 Lulu MagoNero 999 139 21 33 119 117 +PG0008 Yuna Evocatrice 1019 100 32 17 97 99 +PG0009 DarkCecil CavaliereNero 1901 48 106 90 12 18 +PG0010 Kefka Arcimago 1271 89 39 47 89 64 diff --git a/Laboratorio 7/Esercizio 1/pgList.c b/Laboratorio 7/Esercizio 1/pgList.c new file mode 100644 index 0000000..facedf5 --- /dev/null +++ b/Laboratorio 7/Esercizio 1/pgList.c @@ -0,0 +1,131 @@ +// Laboratorio 7 - Esercizio 1 - pgList.c +// Matteo Schiff - s295565 + +#ifndef PGLIST_C_DEFINED +#define PGLIST_C_DEFINED + +#include +#include +#include + +#include "pgList.h" + +typedef struct node_s *link; + +typedef struct node_s { + pg_t val; + link next; +} node; + +/* ADT di prima classe collezione di personaggi */ +typedef struct pgList_s { + link head; + link tail; + int nPg; +} *pgList_t; + +link new_node(pg_t val, link next) { + link t = malloc(sizeof(node)); + if (t == NULL) { + printf("ERROR: out of memory"); + exit(2); + } + t->val = val; + t->next = next; + + return t; +} + +void free_node(link p) { + pg_clean(&p->val); + free(p); +} + +/* creatore e distruttore */ +pgList_t pgList_init() { + pgList_t new = malloc(sizeof(struct pgList_s)); + new->head = NULL; + new->tail = NULL; + new->nPg = 0; + return new; +} + +void pgList_free(pgList_t pgList) { + link p, x; + for (p = pgList->head, x = pgList->head->next; x != NULL; p = x, x = x->next){ + free_node(p); + } + free(pgList); +} + +/* lettura e scrittura su file */ +void pgList_read(FILE *fp, pgList_t pgList) { + while (!feof(fp)) + { + pg_t pgp; + if (pg_read(fp, &pgp) != 0) { + pgList_insert(pgList, pgp); + } + } +} + +void pgList_print(FILE *fp, pgList_t pgList, invArray_t invArray) { + link p; + + for (p = pgList->head; p != NULL; p = p->next) { + pg_print(fp, &(p->val), invArray); + } +} + +/* inserimento di un nuovo personaggio */ +void pgList_insert(pgList_t pgList, pg_t pg) { + link new = new_node(pg, NULL); + if (pgList->head == NULL) { + pgList->head = new; + } else { + pgList->tail->next = new; + } + + pgList->tail = new; +} +/* cancellazione con rimozione */ +void pgList_remove(pgList_t pgList, char* cod) { + link p, x; + + if (pgList->head == NULL) + return; + + for (x = pgList->head, p = NULL; x != NULL; p = x, x = x->next) { + if (!strcmp(x->val.cod, cod)) { + if (p == NULL) { + pgList->head = x->next; + } else { + p->next = x->next; + + // se tolgo l'ultimo elemento devo aggiornare `tail` + if (x->next == NULL) + pgList->tail = p; + } + + free_node(x); + break; + } + } +} + +/* ricerca per codice, ritornando il puntatore */ +pg_t *pgList_searchByCode(pgList_t pgList, char* cod) { + link p; + + for (p = pgList->head; p != NULL; p = p->next) { + if (!strcmp(p->val.cod, cod)) { + return &(p->val); + } + } + + return NULL; +} + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 7/Esercizio 1/pgList.h b/Laboratorio 7/Esercizio 1/pgList.h new file mode 100644 index 0000000..7024df0 --- /dev/null +++ b/Laboratorio 7/Esercizio 1/pgList.h @@ -0,0 +1,33 @@ +// Laboratorio 7 - Esercizio 1 - pgList.h +// Matteo Schiff - s295565 + +#ifndef PGLIST_H_DEFINED +#define PGLIST_H_DEFINED + +#include +#include +#include + +#include "pg.h" + +/* ADT di prima classe collezione di personaggi */ +typedef struct pgList_s *pgList_t; + +/* creatore e distruttore */ +pgList_t pgList_init(); +void pgList_free(pgList_t pgList); + +/* lettura e scrittura su file */ +void pgList_read(FILE *fp, pgList_t pgList); +void pgList_print(FILE *fp, pgList_t pgList, invArray_t invArray); + +/* inserimento di un nuovo personaggio */ +void pgList_insert(pgList_t pgList, pg_t pg); +/* cancellazione con rimozione */ +void pgList_remove(pgList_t pgList, char* cod); +/* ricerca per codice, ritornando il puntatore */ +pg_t *pgList_searchByCode(pgList_t pgList, char* cod); + +/* Si possono aggiungere altre funzioni se ritenute necessarie */ + +#endif diff --git a/Laboratorio 7/Esercizio 2/Diagonali.c b/Laboratorio 7/Esercizio 2/Diagonali.c new file mode 100644 index 0000000..02701e5 --- /dev/null +++ b/Laboratorio 7/Esercizio 2/Diagonali.c @@ -0,0 +1,73 @@ +// Laboratorio 7 - Esercizio 2 - Diagonali.c +// Matteo Schiff - s295565 + +#include +#include "Elementi.h" +#include "Diagonali.h" + +typedef struct node_s *link; + +typedef struct node_s { + Diagonale diag; + link next; +} node; + +typedef struct diagonali +{ + link head; + int N; +} *Diagonali; + +link new_node(Diagonale diag, link next) { + link t = malloc(sizeof(node)); + if (t == NULL) { + printf("Errore: impossibile allocare memoria"); + exit(2); + } + t->diag = diag; + t->next = next; + + return t; +} + +void free_node(link p) { + free(p); +} + +/* creatore e distruttore */ +Diagonali DiagionaliInit() { + Diagonali new = malloc(sizeof(struct diagonali)); + new->head = NULL; + new->N = 0; + return new; +} + +void DiagonaliFree(Diagonali diags) { + link p, x; + for (p = diags->head, x = diags->head->next; x != NULL; p = x, x = x->next){ + free_node(p); + } + free(diags); +} + +void DiagonaliInsert(Diagonali diags, Diagonale newDiag) { + link nd = new_node(newDiag, diags->head); + diags->head = nd; + diags->N++; +} + +link DiagonaliTraverse(Diagonali diags, link prev, Diagonale ** elem) { + link next; + + if (prev == NULL) { + next = diags->head; + } else { + next = prev->next; + } + + if (next == NULL) + return NULL; + + *elem = &next->diag; + return next; +} diff --git a/Laboratorio 7/Esercizio 2/Diagonali.h b/Laboratorio 7/Esercizio 2/Diagonali.h new file mode 100644 index 0000000..3d43186 --- /dev/null +++ b/Laboratorio 7/Esercizio 2/Diagonali.h @@ -0,0 +1,27 @@ +// Laboratorio 7 - Esercizio 2 - Diagonali.h +// Matteo Schiff - s295565 + +#ifndef DIAG_H_DEFINED +#define DIAG_H_DEFINED +#include "Elementi.h" +#include +#define MAX_ELEM 5 + +typedef struct node_s *link; +typedef struct diagonali *Diagonali; + +typedef struct diagonale { + Elemento elementi[MAX_ELEM]; + int N; + float punti; + int diff; + bool hasFront; + bool hasBack; + bool hasSeq; +} Diagonale; + +Diagonali DiagionaliInit(); +void DiagonaliFree(Diagonali diags); +void DiagonaliInsert(Diagonali diags, Diagonale newDiag); +link DiagonaliTraverse(Diagonali diags, link prev, Diagonale ** elem); +#endif \ No newline at end of file diff --git a/Laboratorio 7/Esercizio 2/Elementi.c b/Laboratorio 7/Esercizio 2/Elementi.c new file mode 100644 index 0000000..f46144c --- /dev/null +++ b/Laboratorio 7/Esercizio 2/Elementi.c @@ -0,0 +1,11 @@ +// Laboratorio 7 - Esercizio 2 - Elementi.c +// Matteo Schiff - s295565 + +#include +#include"Elementi.h" + +Elemento leggiElemento(FILE * fp) { + Elemento e; + fscanf(fp, "%s %d %d %d %d %d %f %d", e.nome, &e.tipo, &e.dirIngresso, &e.dirUscita, (int *) &e.reqPreced, (int *) &e.finale, &e.valore, &e.diff); + return e; +} \ No newline at end of file diff --git a/Laboratorio 7/Esercizio 2/Elementi.h b/Laboratorio 7/Esercizio 2/Elementi.h new file mode 100644 index 0000000..207daa8 --- /dev/null +++ b/Laboratorio 7/Esercizio 2/Elementi.h @@ -0,0 +1,25 @@ +// Laboratorio 7 - Esercizio 2 - Elementi.h +// Matteo Schiff - s295565 + +#ifndef ELEM_H_DEFINED +#define ELEM_H_DEFINED +#include +#include +#define MAX_LEN 30 + +enum tipo { TRANSIZIONE, INDIETRO, AVANTI }; +enum direzione { SPALLE, FRONTE }; + +typedef struct elemento { + char nome[MAX_LEN+1]; + int tipo; + int dirIngresso; + int dirUscita; + bool reqPreced; + bool finale; + float valore; + int diff; +} Elemento; + +Elemento leggiElemento(FILE * fp); +#endif \ No newline at end of file diff --git a/Laboratorio 7/Esercizio 2/elementi.txt b/Laboratorio 7/Esercizio 2/elementi.txt new file mode 100644 index 0000000..04a9dbe --- /dev/null +++ b/Laboratorio 7/Esercizio 2/elementi.txt @@ -0,0 +1,20 @@ +19 +ruota 0 1 0 0 0 0.0 1 +rondata 0 1 0 0 0 0.2 1 +ribaltata_a_2 0 1 1 0 0 0.25 2 +back_handspring 0 0 0 0 0 0.4 2 +front_tuck 2 1 1 0 0 1.75 3 +front_pike 2 1 1 0 0 2.0 4 +front_layout 2 1 1 0 0 2.25 5 +back_tuck 1 0 0 0 0 1.75 3 +back_pike 1 0 0 0 0 2.0 4 +back_layout 1 0 0 0 0 2.25 5 +double_front_tuck 2 1 1 1 0 3.0 6 +double_front_layout 2 1 1 1 1 4.0 7 +double_back_tuck 1 0 0 1 0 3.0 6 +double_back_layout 1 0 0 1 1 4.0 7 +triple_front_tuck 2 1 1 1 1 6.5 8 +triple_back_tuck 1 0 0 1 1 6.0 8 +back_layout_double_twist 1 0 0 1 0 8.0 9 +back_layout_quad_twist 1 0 0 1 1 12.0 10 +arabian 1 0 1 0 0 2.5 4 \ No newline at end of file diff --git a/Laboratorio 7/Esercizio 2/main.c b/Laboratorio 7/Esercizio 2/main.c new file mode 100644 index 0000000..57461ee --- /dev/null +++ b/Laboratorio 7/Esercizio 2/main.c @@ -0,0 +1,189 @@ +// Laboratorio 7 - Esercizio 2 - main.c +// Matteo Schiff - s295565 + +#include +#include +#include +#include "Elementi.h" +#include "Diagonali.h" + +Elemento *leggiFile(char *filename, int *N) +{ + FILE *fin; + if ((fin = fopen(filename, "r")) == NULL) + { + puts("Impossibile aprire il file"); + return NULL; + } + fscanf(fin, "%d", N); + Elemento *lista = malloc(*N * sizeof(Elemento)); + for (int i = 0; i < *N; i++) + { + lista[i] = leggiElemento(fin); + } + fclose(fin); + return lista; +} + +float calcolaPunti(Diagonale diag) +{ + float p = 0; + for (int i = 0; i < diag.N; i++) + { + p += diag.elementi[i].valore; + } + return p; +} + +void generaDiagonaleR(Diagonale tmp, Elemento *scelte, int N_scelte, int max_len, int DD, Diagonali diags) +{ + if (tmp.N > 0 && tmp.N <= max_len) + { + bool el_acr = false; + tmp.hasBack = false; + tmp.hasFront = false; + tmp.hasSeq = false; + for (int i = 0; i < tmp.N; i++) + { + if (tmp.elementi[i].tipo == AVANTI) + { + el_acr = true; + tmp.hasFront = true; + } + if (tmp.elementi[i].tipo == INDIETRO) + { + el_acr = true; + tmp.hasBack = true; + } + } + + for (int i = 0; i 0 && tmp.elementi[tmp.N - 1].finale)) + { + return; + } + + for (int i = 0; i < N_scelte; i++) + { + // Se devo mettere il primo elemento + if (tmp.N == 0) + { + if (scelte[i].reqPreced == true || scelte[i].dirIngresso == SPALLE) + continue; + } + else + { + if (scelte[i].dirIngresso != tmp.elementi[tmp.N - 1].dirUscita) + continue; + } + + if (tmp.diff + scelte[i].diff > DD) + continue; + + tmp.elementi[tmp.N++] = scelte[i]; + tmp.diff += scelte[i].diff; + generaDiagonaleR(tmp, scelte, N_scelte, max_len, DD, diags); + tmp.diff -= scelte[i].diff; + tmp.N--; + } +} + +Diagonali generaDiagonaliValide(Elemento *elementi, int N, int DD) +{ + Diagonali set = DiagionaliInit(); + Diagonale tmp; + tmp.diff = 0; + tmp.N = 0; + + generaDiagonaleR(tmp, elementi, N, 5, DD, set); + + return set; +} + +void trovaProgrammaMiglioreR(Diagonali diag, int c, Diagonale **sel, float *max, Diagonale **res, int DP, int diff) +{ + if (c == 3) + { + bool hasFront = sel[0]->hasFront || sel[1]->hasFront || sel[2]->hasFront; + bool hasBack = sel[0]->hasBack || sel[1]->hasBack || sel[2]->hasBack; + bool hasSeq = sel[0]->hasSeq || sel[1]->hasSeq || sel[2]->hasSeq; + + float puntiUltimaDiag = (sel[2]->elementi[sel[2]->N - 1].valore >= 8) ? sel[2]->punti * 1.5 : sel[2]->punti; + + float points = sel[0]->punti + sel[1]->punti + puntiUltimaDiag; + if (points > *max && diff <= DP && hasFront && hasBack && hasSeq) + { + *max = points; + res[0] = sel[0]; + res[1] = sel[1]; + res[2] = sel[2]; + } + + return; + } + + link p = NULL; + Diagonale *curr; + do + { + p = DiagonaliTraverse(diag, p, &curr); + + if (curr->diff + diff > DP) + continue; + + sel[c] = curr; + diff += curr->diff; + trovaProgrammaMiglioreR(diag, c + 1, sel, max, res, DP, diff); + diff -= curr->diff; + } while (p != NULL); +} + +void stampaDiagonale(Diagonale *diag) +{ + printf("Diagonale: [punti=%f], [difficoltà=%d] -", diag->punti, diag->diff); + for (int i = 0; i < diag->N; i++) + { + printf(" %s", diag->elementi[i].nome); + } + putchar('\n'); +} + +void trovaProgrammaMigliore(Diagonali diags, int DP) +{ + float max = 0; + Diagonale *sel[3]; + Diagonale *res[3]; + trovaProgrammaMiglioreR(diags, 0, sel, &max, res, DP, 0); + + printf("Massimo valore: %f\n", max); + stampaDiagonale(res[0]); + stampaDiagonale(res[1]); + stampaDiagonale(res[2]); +} + +int main() +{ + int N = 0, DP, DD;; + Elemento *l = leggiFile("elementi.txt", &N); + printf("Inserisci DD e DP: "); + scanf("%d %d", &DD, &DP); + Diagonali diags = generaDiagonaliValide(l, N, DD); + + trovaProgrammaMigliore(diags, DP); + + DiagonaliFree(diags); + free(l); + return 0; +} \ No newline at end of file diff --git a/Laboratorio 7/Esercizio 2/testset_risulutati.txt b/Laboratorio 7/Esercizio 2/testset_risulutati.txt new file mode 100644 index 0000000..9d56fe5 --- /dev/null +++ b/Laboratorio 7/Esercizio 2/testset_risulutati.txt @@ -0,0 +1,59 @@ +--- Test Case #1 --- +DD = 10 DP = 20 +TOT = 17.800 +DIAG #1 > 1.750 +front_tuck +DIAG #2 > 3.750 +front_tuck front_pike +DIAG #3 > 8.200 * 1.5 (BONUS) +rondata back_layout_double_twist + +--- Test Case #2 --- +DD = 7 DP = 30 +TOT = 11.200 +DIAG #1 > 3.700 +rondata back_tuck back_tuck +DIAG #2 > 3.750 +front_tuck front_pike +DIAG #3 > 3.750 +front_tuck front_pike + +--- Test Case #3 --- +DD = 10 DP = 35 +TOT = 26.250 +DIAG #1 > 5.750 +front_tuck double_front_layout +DIAG #2 > 8.200 +rondata back_layout_double_twist +DIAG #3 > 8.200 * 1.5 (BONUS) +rondata back_layout_double_twist + +--- Test Case #4 --- +DD = 12 DP = 28 +TOT = 34.000 +DIAG #1 > 12.200 +rondata back_layout_quad_twist +DIAG #2 > 3.500 +front_tuck front_tuck +DIAG #3 > 12.200 * 1.5 (BONUS) +rondata back_layout_quad_twist + +--- Test Case #5 --- +DD = 12 DP = 30 +TOT = 34.950 +DIAG #1 > 4.450 +rondata arabian front_tuck +DIAG #2 > 12.200 +rondata back_layout_quad_twist +DIAG #3 > 12.200 * 1.5 (BONUS) +rondata back_layout_quad_twist + +--- Test Case #6 --- +DD = 11 DP = 33 +TOT = 38.750 +DIAG #1 > 12.200 +rondata back_layout_quad_twist +DIAG #2 > 8.250 +front_tuck triple_front_tuck +DIAG #3 > 12.200 * 1.5 (BONUS) +rondata back_layout_quad_twist \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 1/Elementi.c b/Laboratorio 8/Esercizio 1/Elementi.c new file mode 100644 index 0000000..ee2daee --- /dev/null +++ b/Laboratorio 8/Esercizio 1/Elementi.c @@ -0,0 +1,11 @@ +// Laboratorio 8 - Esercizio 1 - Elementi.c +// Matteo Schiff - s295565 + +#include +#include"Elementi.h" + +Elemento leggiElemento(FILE * fp) { + Elemento e; + fscanf(fp, "%s %d %d %d %d %d %f %d", e.nome, &e.tipo, &e.dirIngresso, &e.dirUscita, (int *) &e.reqPreced, (int *) &e.finale, &e.valore, &e.diff); + return e; +} \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 1/Elementi.h b/Laboratorio 8/Esercizio 1/Elementi.h new file mode 100644 index 0000000..5f818d5 --- /dev/null +++ b/Laboratorio 8/Esercizio 1/Elementi.h @@ -0,0 +1,25 @@ +// Laboratorio 8 - Esercizio 1 - Elementi.h +// Matteo Schiff - s295565 + +#ifndef ELEM_H_DEFINED +#define ELEM_H_DEFINED +#include +#include +#define MAX_LEN 30 + +enum tipo { TRANSIZIONE, INDIETRO, AVANTI }; +enum direzione { SPALLE, FRONTE }; + +typedef struct elemento { + char nome[MAX_LEN+1]; + int tipo; + int dirIngresso; + int dirUscita; + bool reqPreced; + bool finale; + float valore; + int diff; +} Elemento; + +Elemento leggiElemento(FILE * fp); +#endif \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 1/elementi.txt b/Laboratorio 8/Esercizio 1/elementi.txt new file mode 100644 index 0000000..04a9dbe --- /dev/null +++ b/Laboratorio 8/Esercizio 1/elementi.txt @@ -0,0 +1,20 @@ +19 +ruota 0 1 0 0 0 0.0 1 +rondata 0 1 0 0 0 0.2 1 +ribaltata_a_2 0 1 1 0 0 0.25 2 +back_handspring 0 0 0 0 0 0.4 2 +front_tuck 2 1 1 0 0 1.75 3 +front_pike 2 1 1 0 0 2.0 4 +front_layout 2 1 1 0 0 2.25 5 +back_tuck 1 0 0 0 0 1.75 3 +back_pike 1 0 0 0 0 2.0 4 +back_layout 1 0 0 0 0 2.25 5 +double_front_tuck 2 1 1 1 0 3.0 6 +double_front_layout 2 1 1 1 1 4.0 7 +double_back_tuck 1 0 0 1 0 3.0 6 +double_back_layout 1 0 0 1 1 4.0 7 +triple_front_tuck 2 1 1 1 1 6.5 8 +triple_back_tuck 1 0 0 1 1 6.0 8 +back_layout_double_twist 1 0 0 1 0 8.0 9 +back_layout_quad_twist 1 0 0 1 1 12.0 10 +arabian 1 0 1 0 0 2.5 4 \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 1/main.c b/Laboratorio 8/Esercizio 1/main.c new file mode 100644 index 0000000..d952301 --- /dev/null +++ b/Laboratorio 8/Esercizio 1/main.c @@ -0,0 +1,345 @@ +// Laboratorio 8 - Esercizio 1 - main.c +// Matteo Schiff - s295565 + +#include +#include +#include +#include "Elementi.h" +#define MAX_ELEM 5 +#define MAX_DIAG 3 + +typedef struct params +{ + bool acrobNecessaria; + bool acrobAvantiNecessaria; + bool acrobIndietroNecessaria; +} Requirements; + +Elemento *leggiFile(char *filename, int *N) +{ + FILE *fin; + if ((fin = fopen(filename, "r")) == NULL) + { + puts("Impossibile aprire il file"); + return NULL; + } + fscanf(fin, "%d", N); + Elemento *lista = malloc(*N * sizeof(Elemento)); + for (int i = 0; i < *N; i++) + { + lista[i] = leggiElemento(fin); + } + fclose(fin); + return lista; +} + +float calcElementValue(Elemento e, Requirements reqs, bool acrobInSeqNecessaria) +{ + float value = (e.valore / e.diff); + + if (e.tipo == AVANTI && reqs.acrobAvantiNecessaria) + { + value += 1; + } + + if (e.tipo == INDIETRO && reqs.acrobIndietroNecessaria) + { + value += 1; + } + + if (e.tipo > 0 && reqs.acrobNecessaria) + { + value += 1; + } + + if (e.tipo > 0 && acrobInSeqNecessaria) + { + value += 1; + } + + return value; +} + +// variabili passate come contesto alla funzione di confronto chiamata da qsort +Requirements context; +bool acrobInSeqNecessariaSort; + +int greedyChoice(const void *a, const void *b) +{ + Elemento x = *(Elemento *)a; + Elemento y = *(Elemento *)b; + + float va = calcElementValue(x, context, acrobInSeqNecessariaSort); + float vb = calcElementValue(y, context, acrobInSeqNecessariaSort); + + return vb > va; +} + +void swap(int *a, int *b) +{ + int c = *a; + *a = *b; + *b = c; +} + +void swapE(Elemento *a, Elemento *b) +{ + Elemento c = *a; + *a = *b; + *b = c; +} + +void sortAccettabili(Elemento *accettabili, int N, Requirements *reqs, bool acrobInSeqNecessaria) +{ + context = *reqs; + acrobInSeqNecessariaSort = acrobInSeqNecessaria; + qsort(accettabili, N, sizeof(Elemento), greedyChoice); +} + +int getAccettabili(Elemento *accettabili, Elemento *elementi, int N, int DD, int DP, Elemento *soluzione, int posizioneAssoluta, int posInDiag, int currKp, int diffDiags[MAX_DIAG], int diffTot) +{ + int N_accettabili = 0; + + for (int i = 0; i < N; i++) + { + if (diffDiags[currKp] + elementi[i].diff > DD || diffTot + elementi[i].diff > DP) + continue; + + if (posInDiag == 0 && elementi[i].dirIngresso != FRONTE) + continue; + + if (posInDiag > 0 && elementi[i].dirIngresso != soluzione[posizioneAssoluta - 1].dirUscita) + continue; + + if (posInDiag == 0 && elementi[i].reqPreced) + continue; + + accettabili[N_accettabili++] = elementi[i]; + } + + return N_accettabili; +} + +void stampaSoluzione(Elemento *soluzione, int *diagSize) +{ + float totPoints = 0, diagPoints; + + for (int i = 0; i < MAX_DIAG; i++) + { + diagPoints = 0; + for (int j = 0; j < diagSize[i]; j++) + { + diagPoints += soluzione[i * MAX_ELEM + j].valore; + } + printf("DIAG #%d > %.3f", i + 1, diagPoints); + if (i == MAX_DIAG - 1 && soluzione[diagSize[i] + i * MAX_ELEM - 1].diff >= 8) + { + printf(" * 1.5 (BONUS)"); + diagPoints *= 1.5; + } + printf("\n"); + totPoints += diagPoints; + for (int j = 0; j < diagSize[i]; j++) + { + printf("%s ", soluzione[i * MAX_ELEM + j].nome); + } + printf("\n"); + } + printf("TOT = %.3f\n", totPoints); +} + +void trovaProgrammaGreedy(Elemento *elementi, int N, int DD, int DP) +{ + int diffDiags[MAX_DIAG] = {0}; + int tmp, minDiffAvanti = DD, minDiffIndietro = DD; + Requirements reqs[MAX_DIAG]; + bool found; + bool contieneElemFinale[MAX_DIAG]; + bool acrobInSeqNecessaria = true; + + for (int i = 0; i < N; i++) + { + if (elementi[i].diff < minDiffAvanti && elementi[i].tipo == AVANTI) + minDiffAvanti = elementi[i].diff; + if (elementi[i].diff < minDiffIndietro && elementi[i].tipo == INDIETRO) + minDiffIndietro = elementi[i].diff; + } + + for (int i = 0; i < MAX_DIAG; i++) + { + contieneElemFinale[i] = false; + reqs[i].acrobAvantiNecessaria = reqs[i].acrobIndietroNecessaria = reqs[i].acrobNecessaria = true; + } + + int *diagSize = (int *)malloc(MAX_DIAG * sizeof(int)); + for (int i = 0; i < MAX_DIAG; i++) + diagSize[i] = 0; + Elemento *soluzione = (Elemento *)malloc(MAX_DIAG * MAX_ELEM * sizeof(Elemento)); + Elemento *accettabili = (Elemento *)malloc(N * sizeof(Elemento)); + + int diffTot = 0; + for (int numElem = 0; numElem < MAX_ELEM; numElem++) + { + for (int numDiag = 0; numDiag < MAX_DIAG; numDiag++) + { + int posizioneAssoluta = numElem + numDiag * MAX_ELEM; + if (!contieneElemFinale[numDiag]) + { + int numAcc = getAccettabili(accettabili, elementi, N, DD, DP, soluzione, posizioneAssoluta, numElem, numDiag, diffDiags, diffTot); + if (numAcc > 0) + { + // Ordinamento descrescente delle scelte possibili + sortAccettabili(accettabili, numAcc, &reqs[numDiag], acrobInSeqNecessaria); + if (reqs[numDiag].acrobAvantiNecessaria != reqs[numDiag].acrobIndietroNecessaria) + { + found = false; + if (reqs[numDiag].acrobAvantiNecessaria) + { + for (int i = 0; i < numAcc && !found; i++) + { + // Scelgo la prima diagonale che soddisfa la condizione + if (accettabili[i].tipo == AVANTI) + { + found = true; + soluzione[posizioneAssoluta] = accettabili[i]; + diagSize[numDiag]++; + } + } + + if (!found) + { + for (int i = 0; i < numAcc && !found; i++) + { + // "cambio" la direzione in uscita dell'ultimo elemento in modo che nell'iterazione dopo si possa provare ad inserire un elemento acrobatico + if (accettabili[i].dirIngresso != accettabili[i].dirUscita && diffDiags[numDiag] + accettabili[i].diff + minDiffAvanti <= DD && !accettabili[i].finale) + { + soluzione[posizioneAssoluta] = accettabili[i]; + diagSize[numDiag]++; + found = true; + // voglio vincolare l'inserimento della acrobazia nell'iterazione successiva (rispetto alle posizioni degli elementi) a questa diagonale + for (tmp = 0; tmp < MAX_DIAG; tmp++) + reqs[tmp].acrobAvantiNecessaria = false; + reqs[numDiag].acrobAvantiNecessaria = true; + } + } + if (!found) + { + // Effettuo la scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[0]; + diagSize[numDiag]++; + } + } + } + + if (reqs[numDiag].acrobIndietroNecessaria) + { + for (int i = 0; i < numAcc && !found; i++) + { + if (accettabili[i].tipo == INDIETRO) + { + found = true; + // Effettuo la scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[i]; + diagSize[numDiag]++; + } + } + + if (!found) + { + found = false; + for (int i = 0; i < numAcc && !found; i++) + { + if (accettabili[i].dirIngresso != accettabili[i].dirUscita && diffDiags[numDiag] + accettabili[i].diff + minDiffIndietro <= DD && !accettabili[i].finale) + { + soluzione[posizioneAssoluta] = accettabili[i]; + diagSize[numDiag]++; + for (tmp = 0; tmp < MAX_DIAG; tmp++) + reqs[tmp].acrobIndietroNecessaria = false; + reqs[numDiag].acrobIndietroNecessaria = true; + found = true; + } + } + if (!found) + { + // Effettuo scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[0]; + diagSize[numDiag]++; + } + } + } + } + else + { + // Effettuo scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[0]; + diagSize[numDiag]++; + } + + // Aggiorno le difficoltà di ogni diagonale + diffDiags[numDiag] += soluzione[posizioneAssoluta].diff; + diffTot += soluzione[posizioneAssoluta].diff; + + // Aggiorno i parametri della funzione obiettivo + if (soluzione[posizioneAssoluta].tipo == AVANTI) + { + for (int i = 0; i < MAX_DIAG; i++) + reqs[i].acrobAvantiNecessaria = false; + } + if (soluzione[posizioneAssoluta].tipo == INDIETRO) + { + for (int i = 0; i < MAX_DIAG; i++) + reqs[i].acrobIndietroNecessaria = false; + } + + if (numElem > 0 && soluzione[posizioneAssoluta].tipo > 0 && soluzione[posizioneAssoluta - 1].tipo > 0) + { + acrobInSeqNecessaria = false; + } + + if (soluzione[posizioneAssoluta].finale) + { + // Blocco l'inserimento di elementi nella diagonale + contieneElemFinale[numDiag] = true; + } + } + } + } + } + + // Cerco la diagonale con l'elemento che permette di ottenere il bonus + int bonusDiag = -1; + for (int numDiag = 0; numDiag < MAX_DIAG; numDiag++) + { + if (soluzione[diagSize[numDiag] + numDiag * MAX_ELEM - 1].diff >= 8) + bonusDiag = numDiag; + } + + // Sposto se ho trovato una diagonale idonea al bonus che non è già in ultima posizione + if (bonusDiag != -1 && bonusDiag != MAX_DIAG - 1) + { + swap(&diagSize[MAX_DIAG - 1], &diagSize[bonusDiag]); + for (int i = 0; i < MAX_ELEM; i++) + swapE(&soluzione[i + (MAX_DIAG - 1) * MAX_ELEM], &soluzione[i + bonusDiag * MAX_ELEM]); + } + + stampaSoluzione(soluzione, diagSize); + + free(accettabili); + free(soluzione); + free(diagSize); + return; +} + +int main() +{ + int N = 0, DP, DD; + ; + Elemento *l = leggiFile("elementi.txt", &N); + printf("Inserisci DD e DP: "); + scanf("%d %d", &DD, &DP); + + trovaProgrammaGreedy(l, N, DD, DP); + + free(l); + return 0; +} \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 1/main2.c b/Laboratorio 8/Esercizio 1/main2.c new file mode 100644 index 0000000..9745215 --- /dev/null +++ b/Laboratorio 8/Esercizio 1/main2.c @@ -0,0 +1,297 @@ +#include +#include +#include +#include "Elementi.h" +#define MAX_ELEM 5 +#define MAX_DIAG 3 + +typedef struct params { + bool acrobNecessaria; + bool acrobAvantiNecessaria; + bool acrobIndietroNecessaria; +} Requirements; + +Elemento *leggiFile(char *filename, int *N) +{ + FILE *fin; + if ((fin = fopen(filename, "r")) == NULL) + { + puts("Impossibile aprire il file"); + return NULL; + } + fscanf(fin, "%d", N); + Elemento *lista = malloc(*N * sizeof(Elemento)); + for (int i = 0; i < *N; i++) + { + lista[i] = leggiElemento(fin); + } + fclose(fin); + return lista; +} + +float calcElementValue(Elemento e, Requirements reqs, bool acrobInSeqNecessaria) { + float value = (e.valore / e.diff); + + if (e.tipo == AVANTI && reqs.acrobAvantiNecessaria) { + value += 1; + } + + if (e.tipo == INDIETRO && reqs.acrobIndietroNecessaria) { + value += 1; + } + + if (e.tipo > 0 && reqs.acrobNecessaria) { + value += 1; + } + + if (e.tipo > 0 && acrobInSeqNecessaria) { + value += 1; + } + + return value; +} + +// variabili passate come contesto alla funzione di confronto chiamata da qsort +Requirements context; +bool acrobInSeqNecessariaSort; + +int greedyChoice(const void *a, const void *b) { + Elemento x = *(Elemento *)a; + Elemento y = *(Elemento *)b; + + float va = calcElementValue(x, context, acrobInSeqNecessariaSort); + float vb = calcElementValue(y, context, acrobInSeqNecessariaSort); + + return vb > va; +} + +void sortAccettabili(Elemento *accettabili, int N, Requirements *reqs, bool acrobInSeqNecessaria) { + context = *reqs; + acrobInSeqNecessariaSort = acrobInSeqNecessaria; + qsort(accettabili, N, sizeof(Elemento), greedyChoice); +} + +int getAccettabili(Elemento *accettabili, Elemento *elementi, int N, int DD, int DP, Elemento *soluzione, int posizioneAssoluta, int posInDiag, int currKp, int diffDiags[MAX_DIAG], int diffTot) { + int N_accettabili = 0; + + for (int i = 0; i < N; i++) { + if (diffDiags[currKp] + elementi[i].diff > DD || diffTot + elementi[i].diff > DP) + continue; + + if (posInDiag == 0 && elementi[i].dirIngresso != FRONTE) + continue; + + if (posInDiag > 0 && elementi[i].dirIngresso != soluzione[posizioneAssoluta-1].dirUscita) + continue; + + if (posInDiag == 0 && elementi[i].reqPreced) + continue; + + accettabili[N_accettabili++] = elementi[i]; + } + + return N_accettabili; +} + +void stampaSoluzione(Elemento *sol, int N, int *kp) { + int i, j, diagonaleBonus = -1; + float tot = 0, parz; + + // Ricerca possibile diagonale con elemento bonus + for (i = 0; i < MAX_DIAG && diagonaleBonus == -1; i++) { + for (j = 0; j < MAX_ELEM && diagonaleBonus == -1; j++) { + if ((kp[j + MAX_ELEM * i] == -1 || j == MAX_ELEM - 1) && sol[j + MAX_ELEM * i - 1].diff >= 8) { + diagonaleBonus = i; + } + } + } + + // Scambio diagonale bonus, se trovata, con l'ultima diagonale + if (diagonaleBonus != -1 && diagonaleBonus != MAX_DIAG - 1) { + for (i = 0; i < N; i++) { + if (kp[i] == diagonaleBonus) kp[i] = MAX_DIAG; + if (kp[i] == MAX_DIAG - 1) kp[i] = diagonaleBonus; + } + for (i = 0; i < N; i++) { + if (kp[i] == MAX_DIAG) kp[i] = MAX_DIAG - 1; + } + diagonaleBonus = MAX_DIAG - 1; + } + + for (j = 0; j < MAX_DIAG; j++) { + parz = 0; + for (i = 0; i < N; i++) { + if (kp[i] == j) { + parz += sol[i].valore; + } + } + printf("DIAG #%d > %.3f", j+1, parz); + if (j == diagonaleBonus) + printf(" * 1.5 (BONUS)"); + printf("\n"); + if (j == diagonaleBonus) { + parz = parz * 1.5; + } + tot += parz; + for (i = 0; i < N; i++) { + if (kp[i] == j) { + printf("%s ", sol[i].nome); + } + } + printf("\n"); + } + printf("TOT = %.3f\n", tot); +} + +void trovaProgrammaGreedy(Elemento *elementi, int N, int DD, int DP) { + int diffDiags[MAX_DIAG] = {0}; + int tmp, minDiffAvanti = DD, minDiffIndietro = DD; + Requirements reqs[MAX_DIAG]; + bool found; + bool contieneElemFinale[MAX_DIAG]; + bool acrobInSeqNecessaria = true; + + for (int i = 0; i < N; i++) { + if (elementi[i].diff < minDiffAvanti && elementi[i].tipo == AVANTI) + minDiffAvanti = elementi[i].diff; + if (elementi[i].diff < minDiffIndietro && elementi[i].tipo == INDIETRO) + minDiffIndietro = elementi[i].diff; + } + + for (int i = 0; i < MAX_DIAG; i++) { + contieneElemFinale[i] = false; + reqs[i].acrobAvantiNecessaria = reqs[i].acrobIndietroNecessaria = reqs[i].acrobNecessaria = true; + } + + int *kp = (int *) malloc(MAX_DIAG * MAX_ELEM * sizeof(int)); + for (int i = 0; i < MAX_DIAG * MAX_ELEM; i++) + kp[i] = -1; + Elemento *soluzione = (Elemento *) malloc(MAX_DIAG * MAX_ELEM * sizeof(Elemento)); + Elemento *accettabili = (Elemento *) malloc(N * sizeof(Elemento)); + + int diffTot = 0; + for (int numElem = 0; numElem < MAX_ELEM; numElem++) { + for (int numDiag = 0; numDiag < MAX_DIAG; numDiag++) { + int posizioneAssoluta = numElem + numDiag * MAX_ELEM; + if (!contieneElemFinale[numDiag]) { + int numAcc = getAccettabili(accettabili, elementi, N, DD, DP, soluzione, posizioneAssoluta, numElem, numDiag, diffDiags, diffTot); + if (numAcc > 0) { + // Ordinamento descrescente delle scelte possibili + sortAccettabili(accettabili, numAcc, &reqs[numDiag], acrobInSeqNecessaria); + if (reqs[numDiag].acrobAvantiNecessaria != reqs[numDiag].acrobIndietroNecessaria) { + found = false; + if (reqs[numDiag].acrobAvantiNecessaria) { + for (int i = 0; i < numAcc && !found; i++) { + // Scelgo la prima diagonale che soddisfa la condizione + if (accettabili[i].tipo == AVANTI) { + found = true; + soluzione[posizioneAssoluta] = accettabili[i]; + kp[posizioneAssoluta] = numDiag; + } + } + + if (!found) { + for (int i = 0; i < numAcc && !found; i++) { + if (accettabili[i].dirIngresso != accettabili[i].dirUscita && diffDiags[numDiag] + accettabili[i].diff + minDiffAvanti <= DD && !accettabili[i].finale) { + soluzione[posizioneAssoluta] = accettabili[i]; + kp[posizioneAssoluta] = numDiag; + found = true; + for (tmp = 0; tmp < MAX_DIAG; tmp++) + reqs[tmp].acrobAvantiNecessaria = false; + reqs[numDiag].acrobAvantiNecessaria = true; + + } + } + if (!found) { + // Effettuo scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[0]; + kp[posizioneAssoluta] = numDiag; + } + } + } + + if (reqs[numDiag].acrobIndietroNecessaria) { + for (int i = 0; i < numAcc && !found; i++) { + if (accettabili[i].tipo == INDIETRO) { + found = true; + // Effettuo scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[i]; + kp[posizioneAssoluta] = numDiag; + } + } + + if (!found) { + found = false; + for (int i = 0; i < numAcc && !found; i++) { + if (accettabili[i].dirIngresso != accettabili[i].dirUscita && diffDiags[numDiag] + accettabili[i].diff + minDiffIndietro <= DD && !accettabili[i].finale) { + soluzione[posizioneAssoluta] = accettabili[i]; + kp[posizioneAssoluta] = numDiag; + for (tmp = 0; tmp < MAX_DIAG; tmp++) + reqs[tmp].acrobIndietroNecessaria = false; + reqs[numDiag].acrobIndietroNecessaria = true; + found = true; + } + } + if (!found) { + // Effettuo scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[0]; + kp[posizioneAssoluta] = numDiag; + } + } + } + } else { + // Effettuo scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[0]; + kp[posizioneAssoluta] = numDiag; + } + + // Aggiornamento difficoltà + diffDiags[numDiag] += soluzione[posizioneAssoluta].diff; + diffTot += soluzione[posizioneAssoluta].diff; + + // Aggiornamento parametri funzione obiettivo + if (soluzione[posizioneAssoluta].tipo == AVANTI) { + for (int i = 0; i < MAX_DIAG; i++) + reqs[i].acrobAvantiNecessaria = false; + reqs[numDiag].acrobIndietroNecessaria = false; + } + if (soluzione[posizioneAssoluta].tipo == INDIETRO) { + for (int i = 0; i < MAX_DIAG; i++) + reqs[i].acrobIndietroNecessaria = false; + reqs[numDiag].acrobAvantiNecessaria = false; + } + + if (numElem > 0 && soluzione[posizioneAssoluta].tipo > 0 && soluzione[posizioneAssoluta-1].tipo > 0) { + for (int i = 0; i < MAX_DIAG; i++) + acrobInSeqNecessaria = false; + } + + if (soluzione[posizioneAssoluta].finale) { + // Blocco l'inserimento di elementi nella diagonale + contieneElemFinale[numDiag] = true; + } + } + } + } + } + + stampaSoluzione(soluzione, MAX_DIAG * MAX_ELEM, kp); + + free(accettabili); + free(soluzione); + free(kp); + return; +} + +int main() +{ + int N = 0, DP, DD;; + Elemento *l = leggiFile("elementi.txt", &N); + printf("Inserisci DD e DP: "); + scanf("%d %d", &DD, &DP); + + trovaProgrammaGreedy(l, N, DD, DP); + + free(l); + return 0; +} \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 1/mainlosttest.c b/Laboratorio 8/Esercizio 1/mainlosttest.c new file mode 100644 index 0000000..fa33173 --- /dev/null +++ b/Laboratorio 8/Esercizio 1/mainlosttest.c @@ -0,0 +1,376 @@ +#include +#include +#include +#include "Elementi.h" +#define MAX_ELEM 5 +#define MAX_DIAG 3 + +typedef struct params +{ + bool acrobNecessaria; +} Requirements; + +typedef struct gparams +{ + bool acrobAvantiNecessaria; + bool acrobIndietroNecessaria; + bool acrobInSeqNecessaria; +} GlobalRequirements; + +Elemento *leggiFile(char *filename, int *N) +{ + FILE *fin; + if ((fin = fopen(filename, "r")) == NULL) + { + puts("Impossibile aprire il file"); + return NULL; + } + fscanf(fin, "%d", N); + Elemento *lista = malloc(*N * sizeof(Elemento)); + for (int i = 0; i < *N; i++) + { + lista[i] = leggiElemento(fin); + } + fclose(fin); + return lista; +} + +float calcElementValue(Elemento e, Requirements reqs, GlobalRequirements greqs) +{ + float value = (e.valore / e.diff); + + if (e.tipo == AVANTI && greqs.acrobAvantiNecessaria) + { + value += 1; + } + + if (e.tipo == INDIETRO && greqs.acrobIndietroNecessaria) + { + value += 1; + } + + if (e.tipo > 0 && reqs.acrobNecessaria) + { + value += 1; + } + + if (e.tipo > 0 && greqs.acrobInSeqNecessaria) + { + value += 1; + } + + return value; +} + +// variabili passate come contesto alla funzione di confronto chiamata da qsort +Requirements context; +GlobalRequirements gcontext; + +int greedyChoice(const void *a, const void *b) +{ + Elemento x = *(Elemento *)a; + Elemento y = *(Elemento *)b; + + float va = calcElementValue(x, context, gcontext); + float vb = calcElementValue(y, context, gcontext); + + return vb > va; +} + +void swap(int *a, int *b) +{ + int c = *a; + *a = *b; + *b = c; +} + +void swapE(Elemento *a, Elemento *b) +{ + Elemento c = *a; + *a = *b; + *b = c; +} + +void sortAccettabili(Elemento *accettabili, int N, Requirements *reqs, GlobalRequirements *greqs) +{ + context = *reqs; + gcontext = *greqs; + qsort(accettabili, N, sizeof(Elemento), greedyChoice); +} + +int getAccettabili(Elemento *accettabili, Elemento *elementi, int N, int DD, int DP, Elemento *soluzione, int posizioneAssoluta, int posInDiag, int currKp, int diffDiags[MAX_DIAG], int diffTot) +{ + int N_accettabili = 0; + + for (int i = 0; i < N; i++) + { + if (diffDiags[currKp] + elementi[i].diff > DD || diffTot + elementi[i].diff > DP) + continue; + + if (posInDiag == 0 && elementi[i].dirIngresso != FRONTE) + continue; + + if (posInDiag > 0 && elementi[i].dirIngresso != soluzione[posizioneAssoluta - 1].dirUscita) + continue; + + if (posInDiag == 0 && elementi[i].reqPreced) + continue; + + accettabili[N_accettabili++] = elementi[i]; + } + + return N_accettabili; +} + +void stampaSoluzione(Elemento *soluzione, int *diagSize) +{ + float totPoints = 0, diagPoints; + + for (int i = 0; i < MAX_DIAG; i++) + { + diagPoints = 0; + for (int j = 0; j < diagSize[i]; j++) + { + diagPoints += soluzione[i * MAX_ELEM + j].valore; + } + printf("DIAG #%d > %.3f", i + 1, diagPoints); + if (i == MAX_DIAG - 1 && soluzione[diagSize[i] + i * MAX_ELEM - 1].diff >= 8) + { + printf(" * 1.5 (BONUS)"); + diagPoints *= 1.5; + } + printf("\n"); + totPoints += diagPoints; + for (int j = 0; j < diagSize[i]; j++) + { + printf("%s ", soluzione[i * MAX_ELEM + j].nome); + } + printf("\n"); + } + printf("TOT = %.3f\n", totPoints); +} + +void trovaProgrammaGreedy(Elemento *elementi, int N, int DD, int DP) +{ + int diffDiags[MAX_DIAG] = {0}; + int tmp, minDiffAvanti = DD, minDiffIndietro = DD; + Requirements reqs[MAX_DIAG]; + GlobalRequirements greqs; + bool found; + bool contieneElemFinale[MAX_DIAG]; + + for (int i = 0; i < N; i++) + { + if (elementi[i].diff < minDiffAvanti && elementi[i].tipo == AVANTI) + minDiffAvanti = elementi[i].diff; + if (elementi[i].diff < minDiffIndietro && elementi[i].tipo == INDIETRO) + minDiffIndietro = elementi[i].diff; + } + + for (int i = 0; i < MAX_DIAG; i++) + { + contieneElemFinale[i] = false; + reqs[i].acrobNecessaria = true; + } + + greqs.acrobAvantiNecessaria = greqs.acrobIndietroNecessaria = greqs.acrobInSeqNecessaria = true; + + int *diagSize = (int *)malloc(MAX_DIAG * sizeof(int)); + for (int i = 0; i < MAX_DIAG; i++) + diagSize[i] = 0; + Elemento *soluzione = (Elemento *)malloc(MAX_DIAG * MAX_ELEM * sizeof(Elemento)); + Elemento *accettabili = (Elemento *)malloc(N * sizeof(Elemento)); + + int diffTot = 0; + for (int numElem = 0; numElem < MAX_ELEM; numElem++) + { + for (int numDiag = 0; numDiag < MAX_DIAG; numDiag++) + { + int posizioneAssoluta = numElem + numDiag * MAX_ELEM; + if (!contieneElemFinale[numDiag]) + { + int numAcc = getAccettabili(accettabili, elementi, N, DD, DP, soluzione, posizioneAssoluta, numElem, numDiag, diffDiags, diffTot); + if (numAcc > 0) + { + // Ordinamento descrescente delle scelte possibili + sortAccettabili(accettabili, numAcc, &reqs[numDiag], &greqs); + if (greqs.acrobAvantiNecessaria != greqs.acrobIndietroNecessaria || reqs->acrobNecessaria) + { + found = false; + if (greqs.acrobAvantiNecessaria) + { + for (int i = 0; i < numAcc && !found; i++) + { + // Scelgo il primo elemento che soddisfa la condizione + if (accettabili[i].tipo == AVANTI) + { + found = true; + soluzione[posizioneAssoluta] = accettabili[i]; + diagSize[numDiag]++; + } + } + + if (!found) + { + for (int i = 0; i < numAcc && !found; i++) + { + if (accettabili[i].dirIngresso != accettabili[i].dirUscita && diffDiags[numDiag] + accettabili[i].diff + minDiffAvanti <= DD && !accettabili[i].finale) + { + soluzione[posizioneAssoluta] = accettabili[i]; + diagSize[numDiag]++; + found = true; + } + } + if (!found) + { + // Effettuo scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[0]; + diagSize[numDiag]++; + } + } + } + else if (greqs.acrobIndietroNecessaria) + { + for (int i = 0; i < numAcc && !found; i++) + { + if (accettabili[i].tipo == INDIETRO) + { + found = true; + // Effettuo scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[i]; + diagSize[numDiag]++; + } + } + + if (!found) + { + found = false; + for (int i = 0; i < numAcc && !found; i++) + { + if (accettabili[i].dirIngresso != accettabili[i].dirUscita && diffDiags[numDiag] + accettabili[i].diff + minDiffIndietro <= DD && !accettabili[i].finale) + { + soluzione[posizioneAssoluta] = accettabili[i]; + diagSize[numDiag]++; + found = true; + } + } + if (!found) + { + // Effettuo scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[0]; + diagSize[numDiag]++; + } + } + } + else + { + if (!greqs.acrobInSeqNecessaria) + { + for (int i = 0; i < numAcc && !found; i++) + { + if (accettabili[i].tipo != TRANSIZIONE && diffDiags[numDiag] + accettabili[i].diff + minDiffAvanti <= DD && !accettabili[i].finale) + { + soluzione[posizioneAssoluta] = accettabili[i]; + diagSize[numDiag]++; + found = true; + } + } + if (!found) + { + // Effettuo scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[0]; + diagSize[numDiag]++; + } + } + else + { + for (int i = 0; i < numAcc && !found; i++) + { + // Scelgo il primo elemento che soddisfa la condizione + if (accettabili[i].tipo != TRANSIZIONE) + { + found = true; + soluzione[posizioneAssoluta] = accettabili[i]; + diagSize[numDiag]++; + if (!greqs.acrobInSeqNecessaria) + { + reqs[i].acrobNecessaria = false; + } + } + } + } + } + } + else + { + // Effettuo scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[0]; + diagSize[numDiag]++; + } + + // Aggiornamento difficoltà + diffDiags[numDiag] += soluzione[posizioneAssoluta].diff; + diffTot += soluzione[posizioneAssoluta].diff; + + // Aggiornamento parametri funzione obiettivo + if (soluzione[posizioneAssoluta].tipo == AVANTI) + { + greqs.acrobAvantiNecessaria = false; + } + if (soluzione[posizioneAssoluta].tipo == INDIETRO) + { + greqs.acrobIndietroNecessaria = false; + } + + if (numElem > 0 && soluzione[posizioneAssoluta].tipo > 0 && soluzione[posizioneAssoluta - 1].tipo > 0) + { + greqs.acrobInSeqNecessaria = false; + } + + if (soluzione[posizioneAssoluta].finale) + { + // Blocco l'inserimento di elementi nella diagonale + contieneElemFinale[numDiag] = true; + } + } + } + } + } + + // Cerco la diagonale con l'elemento che permette di ottenere il bonus + int bonusDiag = -1; + for (int numDiag = 0; numDiag < MAX_DIAG; numDiag++) + { + if (soluzione[diagSize[numDiag] + numDiag * MAX_ELEM - 1].diff >= 8) + bonusDiag = numDiag; + } + + // Sposto se ho trovato un elemento con bonus che non è già in ultima posizione + if (bonusDiag != -1 && bonusDiag != MAX_DIAG - 1) + { + swap(&diagSize[MAX_DIAG - 1], &diagSize[bonusDiag]); + for (int i = 0; i < MAX_ELEM; i++) + swapE(&soluzione[i + (MAX_DIAG - 1) * MAX_ELEM], &soluzione[i + bonusDiag * MAX_ELEM]); + } + + stampaSoluzione(soluzione, diagSize); + + free(accettabili); + free(soluzione); + free(diagSize); + return; +} + +int main() +{ + int N = 0, DP, DD; + ; + Elemento *l = leggiFile("elementi.txt", &N); + printf("Inserisci DD e DP: "); + scanf("%d %d", &DD, &DP); + + trovaProgrammaGreedy(l, N, DD, DP); + + free(l); + return 0; +} \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 1/mainstr.c b/Laboratorio 8/Esercizio 1/mainstr.c new file mode 100644 index 0000000..99887b2 --- /dev/null +++ b/Laboratorio 8/Esercizio 1/mainstr.c @@ -0,0 +1,301 @@ +#include +#include +#include +#include "Elementi.h" +#define MAX_ELEM 5 +#define MAX_DIAG 3 + +typedef struct params { + bool acrobNecessaria; + bool acrobAvantiNecessaria; + bool acrobIndietroNecessaria; + bool haAcrobInSeq; + bool acrobInSeqNecessaria; +} Requirements; + +Elemento *leggiFile(char *filename, int *N) +{ + FILE *fin; + if ((fin = fopen(filename, "r")) == NULL) + { + puts("Impossibile aprire il file"); + return NULL; + } + fscanf(fin, "%d", N); + Elemento *lista = malloc(*N * sizeof(Elemento)); + for (int i = 0; i < *N; i++) + { + lista[i] = leggiElemento(fin); + } + fclose(fin); + return lista; +} + +float calcElementValue(Elemento e, Requirements reqs) { + float value = (e.valore / e.diff); + + if (e.tipo == AVANTI && reqs.acrobAvantiNecessaria) { + value += 1; + } + + if (e.tipo == INDIETRO && reqs.acrobIndietroNecessaria) { + value += 1; + } + + if (e.tipo > 0 && reqs.acrobNecessaria) { + value += 1; + } + + if (e.tipo > 0 && reqs.acrobInSeqNecessaria) { + value += 1; + } + + return value; +} + +Requirements context; + +int greedyChoice(const void *a, const void *b) { + Elemento x = *(Elemento *)a; + Elemento y = *(Elemento *)b; + + float va = calcElementValue(x, context); + float vb = calcElementValue(y, context); + + return vb > va; +} + +void sortAccettabili(Elemento *accettabili, int N, Requirements *reqs) { + context = *reqs; + qsort(accettabili, N, sizeof(Elemento), greedyChoice); +} + +int getAccettabili(Elemento *accettabili, Elemento *elementi, int N, int DD, int DP, Elemento *soluzione, int posizioneAssoluta, int posInDiag, int currKp, int diffDiags[MAX_DIAG], int diffTot) { + int N_accettabili = 0; + + for (int i = 0; i < N; i++) { + if (diffDiags[currKp] + elementi[i].diff > DD || diffTot + elementi[i].diff > DP) + continue; + + if (posInDiag == 0 && elementi[i].dirIngresso != FRONTE) + continue; + + if (posInDiag > 0 && elementi[i].dirIngresso != soluzione[posizioneAssoluta-1].dirUscita) + continue; + + if (posInDiag == 0 && elementi[i].reqPreced) + continue; + + accettabili[N_accettabili++] = elementi[i]; + } + + return N_accettabili; +} + +void stampaSoluzione(Elemento *sol, int N, int *kp) { + int i, j, bonusKp = -1; + float tot = 0, parz; + + // Ricerca possibile diagonale con elemento bonus + for (i = 0; i < MAX_DIAG && bonusKp == -1; i++) { + for (j = 0; j < MAX_ELEM && bonusKp == -1; j++) { + if ((kp[j + MAX_ELEM * i] == -1 || j == MAX_ELEM - 1) && sol[j + MAX_ELEM * i - 1].diff >= 8) { + bonusKp = i; + } + } + } + + // Scambio diagonale bonus, se trovata, con l'ultima diagonale + if (bonusKp != -1 && bonusKp != MAX_DIAG - 1) { + for (i = 0; i < N; i++) { + if (kp[i] == bonusKp) kp[i] = MAX_DIAG; + if (kp[i] == MAX_DIAG - 1) kp[i] = bonusKp; + } + for (i = 0; i < N; i++) { + if (kp[i] == MAX_DIAG) kp[i] = MAX_DIAG - 1; + } + bonusKp = MAX_DIAG - 1; + } + + for (j = 0; j < MAX_DIAG; j++) { + parz = 0; + for (i = 0; i < N; i++) { + if (kp[i] == j) { + parz += sol[i].valore; + } + } + printf("DIAG #%d > %.3f", j+1, parz); + if (j == bonusKp) + printf(" * 1.5 (BONUS)"); + printf("\n"); + if (j == bonusKp) { + parz = parz * 1.5; + } + tot += parz; + for (i = 0; i < N; i++) { + if (kp[i] == j) { + printf("%s ", sol[i].nome); + } + } + printf("\n"); + } + printf("TOT = %.3f\n", tot); +} + +void trovaProgrammaGreedy(Elemento *elementi, int N, int DD, int DP) { + int diffDiags[MAX_DIAG] = {0}; + int tmp, minDiffAvanti = DD, minDiffIndietro = DD; + Requirements reqs[MAX_DIAG]; + bool found; + bool contieneElemFinale[MAX_DIAG]; + + for (int i = 0; i < N; i++) { + if (elementi[i].diff < minDiffAvanti && elementi[i].tipo == AVANTI) + minDiffAvanti = elementi[i].diff; + if (elementi[i].diff < minDiffIndietro && elementi[i].tipo == INDIETRO) + minDiffIndietro = elementi[i].diff; + } + + for (int i = 0; i < MAX_DIAG; i++) { + contieneElemFinale[i] = false; + reqs[i].acrobInSeqNecessaria = reqs[i].haAcrobInSeq = false; + reqs[i].acrobAvantiNecessaria = reqs[i].acrobIndietroNecessaria = reqs[i].acrobNecessaria = true; + } + + int *kp = (int *) malloc(MAX_DIAG * MAX_ELEM * sizeof(int)); + for (int i = 0; i < MAX_DIAG * MAX_ELEM; i++) + kp[i] = -1; + Elemento *soluzione = (Elemento *) malloc(MAX_DIAG * MAX_ELEM * sizeof(Elemento)); + Elemento *accettabili = (Elemento *) malloc(N * sizeof(Elemento)); + + int diffTot = 0; + for (int numElem = 0; numElem < MAX_ELEM; numElem++) { + for (int numDiag = 0; numDiag < MAX_DIAG; numDiag++) { + int posizioneAssoluta = numElem + numDiag * MAX_ELEM; + if (!contieneElemFinale[numDiag]) { + int numAcc = getAccettabili(accettabili, elementi, N, DD, DP, soluzione, posizioneAssoluta, numElem, numDiag, diffDiags, diffTot); + if (numAcc > 0) { + // Ordinamento descrescente delle scelte possibili + sortAccettabili(accettabili, numAcc, &reqs[numDiag]); + if (reqs[numDiag].acrobAvantiNecessaria != reqs[numDiag].acrobIndietroNecessaria) { + found = false; + if (reqs[numDiag].acrobAvantiNecessaria) { + for (int i = 0; i < numAcc && !found; i++) { + // Scelgo la prima diagonale che soddisfa la condizione + if (accettabili[i].tipo == AVANTI) { + found = true; + soluzione[posizioneAssoluta] = accettabili[i]; + kp[posizioneAssoluta] = numDiag; + } + } + + if (!found) { + for (int i = 0; i < numAcc && !found; i++) { + if (accettabili[i].dirIngresso != accettabili[i].dirUscita && diffDiags[numDiag] + accettabili[i].diff + minDiffAvanti <= DD && !accettabili[i].finale) { + soluzione[posizioneAssoluta] = accettabili[i]; + kp[posizioneAssoluta] = numDiag; + found = true; + for (tmp = 0; tmp < MAX_DIAG; tmp++) + reqs[tmp].acrobAvantiNecessaria = false; + reqs[numDiag].acrobAvantiNecessaria = true; + + } + } + if (!found) { + // Effettuo scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[0]; + kp[posizioneAssoluta] = numDiag; + } + } + } + + if (reqs[numDiag].acrobIndietroNecessaria) { + for (int i = 0; i < numAcc && !found; i++) { + if (accettabili[i].tipo == INDIETRO) { + found = true; + // Effettuo scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[i]; + kp[posizioneAssoluta] = numDiag; + } + } + + if (!found) { + found = false; + for (int i = 0; i < numAcc && !found; i++) { + if (accettabili[i].dirIngresso != accettabili[i].dirUscita && diffDiags[numDiag] + accettabili[i].diff + minDiffIndietro <= DD && !accettabili[i].finale) { + soluzione[posizioneAssoluta] = accettabili[i]; + kp[posizioneAssoluta] = numDiag; + for (tmp = 0; tmp < MAX_DIAG; tmp++) + reqs[tmp].acrobIndietroNecessaria = false; + reqs[numDiag].acrobIndietroNecessaria = true; + found = true; + } + } + if (!found) { + // Effettuo scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[0]; + kp[posizioneAssoluta] = numDiag; + } + } + } + } else { + // Effettuo scelta localmente ottima + soluzione[posizioneAssoluta] = accettabili[0]; + kp[posizioneAssoluta] = numDiag; + } + + // Aggiornamento difficoltà + diffDiags[numDiag] += soluzione[posizioneAssoluta].diff; + diffTot += soluzione[posizioneAssoluta].diff; + + // Aggiornamento parametri funzione obiettivo + if (soluzione[posizioneAssoluta].tipo == AVANTI) { + for (int i = 0; i < MAX_DIAG; i++) + reqs[i].acrobAvantiNecessaria = false; + reqs[numDiag].acrobIndietroNecessaria = false; + } + if (soluzione[posizioneAssoluta].tipo == INDIETRO) { + for (int i = 0; i < MAX_DIAG; i++) + reqs[i].acrobIndietroNecessaria = false; + reqs[numDiag].acrobAvantiNecessaria = false; + } + + if (numElem > 0 && soluzione[posizioneAssoluta].tipo > 0 && soluzione[posizioneAssoluta-1].tipo > 0) { + for (int i = 0; i < MAX_DIAG; i++) + reqs[i].haAcrobInSeq = true; + } + + if (numElem > 0 && soluzione[posizioneAssoluta-1].tipo > 0 && !reqs[numDiag].haAcrobInSeq) { + reqs[numDiag].acrobInSeqNecessaria = true; + } else + reqs[numDiag].acrobInSeqNecessaria = false; + + if (soluzione[posizioneAssoluta].finale) { + // Skip a prossima diagonale se è stato inserito un elemento finale + contieneElemFinale[numDiag] = true; + } + } + } + } + } + + stampaSoluzione(soluzione, MAX_DIAG * MAX_ELEM, kp); + + free(accettabili); + free(soluzione); + free(kp); + return; +} + +int main() +{ + int N = 0, DP, DD;; + Elemento *l = leggiFile("elementi.txt", &N); + printf("Inserisci DD e DP: "); + scanf("%d %d", &DD, &DP); + + trovaProgrammaGreedy(l, N, DD, DP); + + free(l); + return 0; +} \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 1/testset_risulutati.txt b/Laboratorio 8/Esercizio 1/testset_risulutati.txt new file mode 100644 index 0000000..9d56fe5 --- /dev/null +++ b/Laboratorio 8/Esercizio 1/testset_risulutati.txt @@ -0,0 +1,59 @@ +--- Test Case #1 --- +DD = 10 DP = 20 +TOT = 17.800 +DIAG #1 > 1.750 +front_tuck +DIAG #2 > 3.750 +front_tuck front_pike +DIAG #3 > 8.200 * 1.5 (BONUS) +rondata back_layout_double_twist + +--- Test Case #2 --- +DD = 7 DP = 30 +TOT = 11.200 +DIAG #1 > 3.700 +rondata back_tuck back_tuck +DIAG #2 > 3.750 +front_tuck front_pike +DIAG #3 > 3.750 +front_tuck front_pike + +--- Test Case #3 --- +DD = 10 DP = 35 +TOT = 26.250 +DIAG #1 > 5.750 +front_tuck double_front_layout +DIAG #2 > 8.200 +rondata back_layout_double_twist +DIAG #3 > 8.200 * 1.5 (BONUS) +rondata back_layout_double_twist + +--- Test Case #4 --- +DD = 12 DP = 28 +TOT = 34.000 +DIAG #1 > 12.200 +rondata back_layout_quad_twist +DIAG #2 > 3.500 +front_tuck front_tuck +DIAG #3 > 12.200 * 1.5 (BONUS) +rondata back_layout_quad_twist + +--- Test Case #5 --- +DD = 12 DP = 30 +TOT = 34.950 +DIAG #1 > 4.450 +rondata arabian front_tuck +DIAG #2 > 12.200 +rondata back_layout_quad_twist +DIAG #3 > 12.200 * 1.5 (BONUS) +rondata back_layout_quad_twist + +--- Test Case #6 --- +DD = 11 DP = 33 +TOT = 38.750 +DIAG #1 > 12.200 +rondata back_layout_quad_twist +DIAG #2 > 8.250 +front_tuck triple_front_tuck +DIAG #3 > 12.200 * 1.5 (BONUS) +rondata back_layout_quad_twist \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 2/Graph.c b/Laboratorio 8/Esercizio 2/Graph.c new file mode 100644 index 0000000..4a0c53e --- /dev/null +++ b/Laboratorio 8/Esercizio 2/Graph.c @@ -0,0 +1,316 @@ +// Laboratorio 8 - Esercizio 2 - Graph.c +// Matteo Schiff - s295565 + +#include +#include +#include + +#include "Graph.h" +#include "ST.h" + +typedef struct node *link; +struct node +{ + int id; + int wt; + link next; +}; + +struct graph +{ + int V; + int E; + int **madj; + link *ladj; + link z; + ST tab; +}; + +static link newNode(int id, int wt, link next) +{ + link t = (link)malloc(sizeof(*t)); + t->id = id; + t->wt = wt; + t->next = next; + return t; +} + +static void freeList(link t, link z) +{ + link q, x = t; + if (t == z) + return; + + while (x != z) + { + q = x->next; + free(x); + x = q; + } +} + +static int searchList(link t, link z, int id) +{ + for (link x = t; x != z; x = x->next) + { + if (x->id == id) + return 1; + } + + return 0; +} + +static Edge EDGEcreate(int v, int w, int wt) +{ + Edge e; + e.v = v; + e.w = w; + e.wt = wt; + return e; +} + +// Questa variabile è usata dalla funzione `vertexCompare` che è chiamata da qsort +Graph tmpG; + +static int vertexCompare(const void *a, const void *b) +{ + return (strcmp(STsearchByIndex(tmpG->tab, (*(Edge *)a).w).name, STsearchByIndex(tmpG->tab, (*(Edge *)b).w).name)); +} + +static void EDGEsort(Edge *edges, int N, Graph G) +{ + tmpG = G; + qsort(edges, N, sizeof(Edge), vertexCompare); +} + +Graph GRAPHload(FILE *fin) +{ + int lines = 0, wt; + Graph G; + + Item item1, item2; + + for (char c = getc(fin); c != EOF; c = getc(fin)) + if (c == '\n') // Se leggo un newline aumento il numero delle linee + lines = lines + 1; + + fseek(fin, 0, SEEK_SET); + + G = GRAPHinit(2 * lines); // Alloco sovrastimando il numero di vertici + for (int i = 0; i < lines; i++) + { + item1 = ITEMread(fin); + item2 = ITEMread(fin); + fscanf(fin, " %d", &wt); + + int id1 = GRAPHgetIndex(G, item1); + int id2 = GRAPHgetIndex(G, item2); + + GRAPHinsertE(G, id1, id2, wt); + } + + return G; +} + +void GRAPHinsertE(Graph G, int v, int w, int wt) +{ + if (G->madj[v][w] == 0) + G->E++; + G->madj[v][w] = 1; + G->madj[v][w] = wt; + G->madj[w][v] = 1; + G->madj[w][v] = wt; +} + +void GRAPHremoveE(Graph G, int v, int w) +{ + if (G->madj[v][w] != 0) + G->E--; + G->madj[v][w] = 0; + G->madj[w][v] = 0; +} + +static int **MATRIXinit(int r, int c, int val) +{ + int i, j; + int **t = malloc(r * sizeof(int *)); + for (i = 0; i < r; i++) + t[i] = malloc(c * sizeof(int)); + for (i = 0; i < r; i++) + for (j = 0; j < c; j++) + t[i][j] = val; + return t; +} + +static link *LISTinit(int V, link z) +{ + link *list = (link *)malloc(V * sizeof(link)); + for (int v = 0; v < V; v++) + list[v] = z; + + return list; +} + +Graph GRAPHinit(int V) +{ + Graph G = malloc(sizeof *G); + G->V = 0; + G->E = 0; + G->madj = MATRIXinit(V, V, 0); + G->z = newNode(-1, -1, NULL); + G->ladj = LISTinit(V, G->z); + G->tab = STinit(V); + return G; +} + +void GRAPHfree(Graph G) +{ + int i; + for (i = 0; i < G->V; i++) + free(G->madj[i]); + free(G->madj); + for (i = 0; i < G->V; i++) + { + freeList(G->ladj[i], G->z); + } + free(G->ladj); + free(G->z); + STfree(G->tab); + free(G); +} + +int GRAPHgetIndex(Graph G, Item item) +{ + int id = STsearch(G->tab, item); + if (id == -1) + { + id = STinsert(G->tab, item); + G->V++; + } + return id; +} + +void GRAPHbuildLadj(Graph G) +{ + link t; + + for (int i = 0; i < G->V; i++) + { + freeList(G->ladj[i], G->z); + G->ladj[i] = G->z; + } + + for (int i = 0; i < G->V; i++) + { + for (int j = 0; j < G->V; j++) + { + if (G->madj[i][j] != 0) + G->ladj[i] = newNode(j, G->madj[i][j], G->ladj[i]); + } + } + + for (int i = 0; i < G->V; i++) + { + if (G->ladj[i] != G->z) + { + printf("%d", i); + for (t = G->ladj[i]; t != G->z; t = t->next) + { + printf(" -> (%d,%d)", t->id, t->wt); + } + printf("\n"); + } + } +} + +static int checkAdjacencyM(Graph G, int id1, int id2, int id3) +{ + if (!G->madj[id1][id2] || !G->madj[id1][id3]) + return 0; + + if (!G->madj[id2][id1] || !G->madj[id2][id3]) + return 0; + + if (!G->madj[id3][id1] || !G->madj[id3][id2]) + return 0; + + return 1; +} + +static int checkAdjacencyL(Graph G, int id1, int id2, int id3) +{ + if (!searchList(G->ladj[id1], G->z, id2) || !searchList(G->ladj[id1], G->z, id2)) + return 0; + + if (!searchList(G->ladj[id2], G->z, id1) || !searchList(G->ladj[id2], G->z, id3)) + return 0; + + if (!searchList(G->ladj[id3], G->z, id1) || !searchList(G->ladj[id3], G->z, id2)) + return 0; + + return 1; +} + +void GRAPHCheckVertexAdiacency(Graph G) +{ + puts("Inserisci i tre vertici specificando per ogni vertice \" \""); + Item i1 = ITEMread(stdin); + Item i2 = ITEMread(stdin); + Item i3 = ITEMread(stdin); + + int id1 = STsearch(G->tab, i1); + int id2 = STsearch(G->tab, i2); + int id3 = STsearch(G->tab, i3); + + if (id1 == -1 || id2 == -1 || id3 == -1) + { + puts("Attenzione: vertici non validi"); + return; + } + + if (checkAdjacencyM(G, id1, id2, id3)) + { + puts("I vertici formano un sottografo completo"); + } + else + { + puts("I vertici non formano un sottografo completo"); + } +} + +void GRAPHprintOrdered(Graph G) +{ + Item *items = malloc(G->V * sizeof(Item)); + Edge *edges = malloc(G->V * sizeof(Edge)); + + for (int i = 0; i < G->V; i++) + { + items[i] = STsearchByIndex(G->tab, i); + } + + ITEMsort(items, G->V); + + for (int i = 0; i < G->V; i++) + { + int id = GRAPHgetIndex(G, items[i]); + printf("%s %s:\n", items[i].name, items[i].subnet); + + // Crea lista di edges + int N = 0; + for (int j = 0; j < G->V; j++) + { + if (G->madj[id][j] != 0) + edges[N++] = EDGEcreate(id, j, G->madj[id][j]); + } + + EDGEsort(edges, N, G); + + for (int j = 0; j < N; j++) + { + printf(" - %s %s, peso %d\n", STsearchByIndex(G->tab, edges[j].w).name, STsearchByIndex(G->tab, edges[j].w).subnet, edges[j].wt); + } + } + + free(edges); + free(items); +} \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 2/Graph.h b/Laboratorio 8/Esercizio 2/Graph.h new file mode 100644 index 0000000..29f8133 --- /dev/null +++ b/Laboratorio 8/Esercizio 2/Graph.h @@ -0,0 +1,26 @@ +// Laboratorio 8 - Esercizio 2 - Graph.h +// Matteo Schiff - s295565 + +#ifndef GRAPH_DEFINED +#define GRAPH_DEFINED + +#include +#include"Item.h" +#define MAXC 100 + +typedef struct edge +{ + int v; + int w; + int wt; +} Edge; +typedef struct graph *Graph; +Graph GRAPHinit(int V); +void GRAPHfree(Graph G); +Graph GRAPHload(FILE *fin); +void GRAPHbuildLadj(Graph G); +void GRAPHCheckVertexAdiacency(Graph G); +void GRAPHprintOrdered(Graph G); +int GRAPHgetIndex(Graph G, Item item); +void GRAPHinsertE(Graph G, int v, int w, int wt); +#endif \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 2/Item.c b/Laboratorio 8/Esercizio 2/Item.c new file mode 100644 index 0000000..101c9c9 --- /dev/null +++ b/Laboratorio 8/Esercizio 2/Item.c @@ -0,0 +1,37 @@ +// Laboratorio 8 - Esercizio 2 - Item.c +// Matteo Schiff - s295565 + +#include +#include +#include + +#include "Item.h" + +Item ITEMcreate(char *name, char *subnet) { + Item t; + strncpy(t.name, name, MAX_STR+1); + strncpy(t.subnet, subnet, MAX_STR+1); + return t; +} + +Item ITEMread(FILE * fp) { + Item item; + fscanf(fp, " %s %s", item.name, item.subnet); + return item; +} + +Item ITEMnull() { + Item t; + strcpy(t.name, ""); + strcpy(t.subnet, ""); + + return t; +} + +static int compareItem(const void *a, const void *b) { + return strcmp((*(Item*)a).name, (*(Item*)b).name); +} + +void ITEMsort(Item *v, int N) { + qsort(v, N, sizeof(Item), compareItem); +} \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 2/Item.h b/Laboratorio 8/Esercizio 2/Item.h new file mode 100644 index 0000000..38ecd91 --- /dev/null +++ b/Laboratorio 8/Esercizio 2/Item.h @@ -0,0 +1,23 @@ +// Laboratorio 8 - Esercizio 2 - Item.h +// Matteo Schiff - s295565 + +#ifndef ITEM_DEFINED +#define ITEM_DEFINED + +#include + +#define MAX_STR 30 + +typedef struct item { + char name[MAX_STR+1]; + char subnet[MAX_STR+1]; +} Item; + +Item ITEMcreate(char *name, char *subnet); +Item ITEMread(FILE * fp); + +Item ITEMnull(); + +void ITEMsort(Item *v, int N); + +#endif diff --git a/Laboratorio 8/Esercizio 2/ST.c b/Laboratorio 8/Esercizio 2/ST.c new file mode 100644 index 0000000..1468e72 --- /dev/null +++ b/Laboratorio 8/Esercizio 2/ST.c @@ -0,0 +1,61 @@ +// Laboratorio 8 - Esercizio 2 - ST.c +// Matteo Schiff - s295565 + +#include +#include +#include + +#include "ST.h" +#include "Item.h" + +struct st { + Item *v; + int N; + int maxN; +}; + +ST STinit(int N) { + ST st = (ST) malloc(sizeof(*st)); + + st->v = (Item *) malloc(N * sizeof(Item)); + st->N = 0; + st->maxN = N; + + return st; +} + +void STfree(ST st) { + free(st->v); + free(st); +} + +int STinsert(ST st, Item item) { + if (st->N == st->maxN) { + printf("Errore, spazio esaurito nella ST\n"); + return -1; + } + + st->v[st->N] = item; + st->N++; + return st->N -1; +} + +Item STsearchByIndex(ST st, int index) { + if (index >= st->N) + return ITEMnull(); + + return st->v[index]; +} + +int STsearch(ST st, Item item) { + int i; + for (i = 0; i < st->N; i++) { + if (strcmp(item.name, st->v[i].name) == 0) + return i; + } + return -1; +} + +int STcount(ST st) { + return st->N; +} \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 2/ST.h b/Laboratorio 8/Esercizio 2/ST.h new file mode 100644 index 0000000..03ff8cb --- /dev/null +++ b/Laboratorio 8/Esercizio 2/ST.h @@ -0,0 +1,21 @@ +// Laboratorio 8 - Esercizio 2 - ST.h +// Matteo Schiff - s295565 + +#ifndef ST_DEFINED +#define ST_DEFINED + +#include "Item.h" + +typedef struct st *ST; + +ST STinit(int N); +void STfree(ST st); + +int STinsert(ST st, Item item); + +Item STsearchByIndex(ST st, int index); +int STsearch(ST st, Item item); + +int STcount(ST st); + +#endif \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 2/grafo.txt b/Laboratorio 8/Esercizio 2/grafo.txt new file mode 100644 index 0000000..faee273 --- /dev/null +++ b/Laboratorio 8/Esercizio 2/grafo.txt @@ -0,0 +1,21 @@ +Uriel Net3 Bahamut Net2 99 +Uriel Net3 Igni Net0 45 +Igni Net0 Tatooine Net1 67 +Tatooine Net1 Bahamut Net2 33 +Axii Net0 Igni Net0 42 +Quen Net0 Igni Net0 18 +Shiva Net2 Tatooine Net1 12 +Ifrit Net2 Tatooine Net1 2 +Ramuh Net2 Tatooine Net1 111 +Shiva Net2 Ifrit Net2 46 +Quen Net0 Coruscan Net1 45 +Shiva Net2 Alderaan Net1 98 +Ifrit Net2 Alderaan Net1 13 +Ramuh Net2 Alderaan Net1 9 +Ramuh Net2 Azrael Net3 23 +Axii Net0 Cassiel Net3 13 +Shiva Net2 Cassiel Net3 1 +Shiva Net2 Yrden Net0 17 +Alderaan Net1 Yrden Net0 20 +Cassiel Net3 Yrden Net0 20 +Cassiel Net3 Azrael Net3 9 diff --git a/Laboratorio 8/Esercizio 2/main.c b/Laboratorio 8/Esercizio 2/main.c new file mode 100644 index 0000000..6f6f895 --- /dev/null +++ b/Laboratorio 8/Esercizio 2/main.c @@ -0,0 +1,92 @@ +// Laboratorio 8 - Esercizio 2 - main.c +// Matteo Schiff - s295565 + +#include +#include + +#include"Graph.h" + +#define MAX_LEN 30 + +const int MAXL = 100; + +typedef enum +{ + r_print, + r_adj, + r_build, + r_fine +} t_comandi; + +char *toLower(char *s) +{ + for (char *p = s; *p; p++) + *p = tolower(*p); + return s; +} + +t_comandi leggiComando() +{ + t_comandi c; + char cmd[MAXL]; + char tabella[4][20] = { + "stampa", "adiacenza", "converti", "fine"}; + printf("comando (stampa/adiacenza/converti/fine): "); + scanf("%s", cmd); + toLower(cmd); + c = r_print; + while (c < 4 && strcmp(cmd, tabella[c]) != 0) + c++; + return (c); +} + +void menuParola(Graph G) +{ + t_comandi comando; + int i, continua = 1; + while (continua) + { + comando = leggiComando(); + switch (comando) + { + case r_print: + GRAPHprintOrdered(G); + break; + case r_adj: + GRAPHCheckVertexAdiacency(G); + break; + case r_build: + GRAPHbuildLadj(G); + break; + case r_fine: + continua = 0; + break; + default: + puts("Comando non valido\n"); + } + } +} + +int main(int argc, char const *argv[]) +{ + FILE * fp_read; + Graph G; + if (argc < 1) { + puts("Specifica il file tra gli argomenti"); + return 1; + } + + if ((fp_read = fopen(argv[1], "r")) == NULL) + { + puts("Impossibile aprire il file"); + return 1; + } + G = GRAPHload(fp_read); + fclose(fp_read); + + menuParola(G); + + GRAPHfree(G); + + return 0; +} diff --git a/Laboratorio 8/Esercizio 3/Asset.c b/Laboratorio 8/Esercizio 3/Asset.c new file mode 100644 index 0000000..79a8530 --- /dev/null +++ b/Laboratorio 8/Esercizio 3/Asset.c @@ -0,0 +1,53 @@ +// Laboratorio 8 - Esercizio 3 - Asset.c +// Matteo Schiff - s295565 + +#include +#include +#include "Asset.h" +#include "ExrateBST.h" + +struct asset +{ + char titolo[STR_LEN]; + ExrateBST exrates; +}; + +Asset AssetCreate() { + Asset a = malloc(sizeof(*a)); + a->exrates = ExrateBSTCreate(); + return a; +} + +void AssetFree(Asset a) { + ExrateBSTFree(a->exrates); + free(a); +} + +int AssetCompare(Asset a, Asset b) { + return strcmp(a->titolo, b->titolo); +} + +char * AssetTitle(Asset a) { + return a->titolo; +} + +ExrateBST AssetGetExrates(Asset a) { + return a->exrates; +} + +Asset AssetRead(FILE *fp) { + Asset n = AssetCreate(); + Exrate je; + int Nitems; + + fscanf(fp, " %s %d",n->titolo, &Nitems); + for (int i = 0; i < Nitems; i++) { + ExrateRead(&je, fp); + ExrateBSTInsert(n->exrates, je); + } + return n; +} + +void AssetPrint(Asset a) { + printf(" - %s\n", a->titolo); +} diff --git a/Laboratorio 8/Esercizio 3/Asset.h b/Laboratorio 8/Esercizio 3/Asset.h new file mode 100644 index 0000000..109d6e9 --- /dev/null +++ b/Laboratorio 8/Esercizio 3/Asset.h @@ -0,0 +1,16 @@ +// Laboratorio 8 - Esercizio 3 - Asset.h +// Matteo Schiff - s295565 + +#ifndef ASSET_DEFINED +#define ASSET_DEFINED +#define STR_LEN 20 +#include "ExrateBST.h" + +typedef struct asset *Asset; +void AssetFree(Asset a); +int AssetCompare(Asset a, Asset b); +ExrateBST AssetGetExrates(Asset a); +Asset AssetRead(FILE *fp); +void AssetPrint(Asset a); +char * AssetTitle(Asset a); +#endif diff --git a/Laboratorio 8/Esercizio 3/AssetList.c b/Laboratorio 8/Esercizio 3/AssetList.c new file mode 100644 index 0000000..506af31 --- /dev/null +++ b/Laboratorio 8/Esercizio 3/AssetList.c @@ -0,0 +1,113 @@ +// Laboratorio 8 - Esercizio 3 - AssetList.c +// Matteo Schiff - s295565 + +#include +#include +#include "Asset.h" +#include "AssetList.h" +#include "ExrateBST.h" + +typedef struct node *link; +struct node +{ + Asset asset; + link next; +}; + +struct assetList +{ + link head; + int N; +}; + +static link createNode(Asset asset, link next) +{ + link new = malloc(sizeof(*new)); + new->asset = asset; + new->next = next; + return new; +} + +AssetList AssetListCreate() +{ + AssetList al = malloc(sizeof(*al)); + + al->head = NULL; + al->N = 0; + + return al; +} + +void AssetListFree(AssetList al) +{ + for (link x = al->head, p = x->next; p != NULL; x = p, p = x->next) + { + free(x); + } + free(al); +} + +int AssetListLength(AssetList al) { + return al->N; +} + +void AssetListPrint(AssetList al) { + link h = al->head; + while (h != NULL) { + AssetPrint(h->asset); + h = h->next; + } +} + +Asset * AssetListGet(AssetList al, int index) { + link h; + int i = 0; + + h = al->head; + while (h != NULL) { + if (i == index) + return &(h->asset); + h = h->next; + i++; + } + return NULL; +} + +Asset * AssetListSearch(AssetList al, char * query) { + link h; + + h = al->head; + while (h != NULL) { + if (strcmp(AssetTitle(h->asset), query) == 0) + return &(h->asset); + h = h->next; + } + return NULL; +} + +void AssetListInsert(AssetList al, Asset asset) +{ + link x, p; + if (al->head == NULL) + { + al->head = createNode(asset, al->head); + al->N++; + return; + } + + for (x = al->head, p = x->next; p != NULL; x = p, p = x->next) + { + if (AssetCompare(asset, x->asset) == 0) + { + ExrateBSTMerge(AssetGetExrates(x->asset), AssetGetExrates(asset)); + return; + } + else if (AssetCompare(asset, x->asset) < 0) + { + break; + } + } + + x->next = createNode(asset, p); + al->N++; +} \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 3/AssetList.h b/Laboratorio 8/Esercizio 3/AssetList.h new file mode 100644 index 0000000..57fddd3 --- /dev/null +++ b/Laboratorio 8/Esercizio 3/AssetList.h @@ -0,0 +1,18 @@ +// Laboratorio 8 - Esercizio 3 - AssetList.h +// Matteo Schiff - s295565 + +#ifndef ASSETLIST_DEFINED +#define ASSETLIST_DEFINED +#include "Asset.h" + +typedef struct assetList *AssetList; + +AssetList AssetListCreate(); +void AssetListFree(AssetList al); +void AssetListInsert(AssetList al, Asset asset); +Asset * AssetListGet(AssetList al, int index); +Asset * AssetListSearch(AssetList al, char * query); +void AssetListPrint(AssetList al); +int AssetListLength(AssetList al); + +#endif diff --git a/Laboratorio 8/Esercizio 3/Datetime.c b/Laboratorio 8/Esercizio 3/Datetime.c new file mode 100644 index 0000000..0db0708 --- /dev/null +++ b/Laboratorio 8/Esercizio 3/Datetime.c @@ -0,0 +1,36 @@ +// Laboratorio 8 - Esercizio 3 - Datetime.c +// Matteo Schiff - s295565 + +#include +#include + +#include "Datetime.h" + +int DateTimeCompare(DateTime a, DateTime b) { + if (a.year > b.year) + return 1; + else if (a.year < b.year) + return -1; + + if (a.month > b.month) + return 1; + else if (a.month < b.month) + return -1; + + if (a.day > b.day) + return 1; + else if (a.day < b.day) + return -1; + + return 0; +} + +int DateTimeRead(DateTime * dt, FILE * fp) { + return fscanf(fp, " %d/%d/%d %d:%d", &dt->year, &dt->month,&dt->day,&dt->hours,&dt->minutes) == 5; +} + +int DateRead(DateTime * dt, FILE * fp) { + dt->hours = 0; + dt->minutes = 0; + return fscanf(fp, " %d/%d/%d", &dt->year, &dt->month,&dt->day) == 3; +} \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 3/Datetime.h b/Laboratorio 8/Esercizio 3/Datetime.h new file mode 100644 index 0000000..c8f3de0 --- /dev/null +++ b/Laboratorio 8/Esercizio 3/Datetime.h @@ -0,0 +1,19 @@ +// Laboratorio 8 - Esercizio 3 - Datetime.h +// Matteo Schiff - s295565 + +#ifndef DATETIME_DEFINED +#define DATETIME_DEFINED +#include + +typedef struct datetime { + int day; + int month; + int year; + int hours; + int minutes; +} DateTime; + +int DateTimeCompare(DateTime a, DateTime b); +int DateTimeRead(DateTime * dt, FILE * fp); +int DateRead(DateTime * dt, FILE * fp); +#endif \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 3/Exrate.c b/Laboratorio 8/Esercizio 3/Exrate.c new file mode 100644 index 0000000..cac893b --- /dev/null +++ b/Laboratorio 8/Esercizio 3/Exrate.c @@ -0,0 +1,36 @@ +// Laboratorio 8 - Esercizio 3 - Exrate.c +// Matteo Schiff - s295565 + +#include +#include "Exrate.h" +#include "Datetime.h" + +int ExrateRead(Exrate *e, FILE *fp) +{ + if (!DateTimeRead(&e->datetime, fp)) + { + return 0; + } + + return fscanf(fp, " %d %d", &e->q, &e->n) == 1; +} + +void ExratePrint(Exrate e) +{ + if (e.n == -1) + { + puts("Quotazione non valida"); + } + else + { + printf("Quotazione: %d, numero di transazioni: %d\n", e.q, e.n); + } +} + +Exrate ExrateEmpty() +{ + Exrate e; + e.n = -1; + e.q = -1; + return e; +} \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 3/Exrate.h b/Laboratorio 8/Esercizio 3/Exrate.h new file mode 100644 index 0000000..debb0b8 --- /dev/null +++ b/Laboratorio 8/Esercizio 3/Exrate.h @@ -0,0 +1,16 @@ +// Laboratorio 8 - Esercizio 3 - Exrate.h +// Matteo Schiff - s295565 + +#ifndef EXRATE_DEFINED +#define EXRATE_DEFINED +#include "Datetime.h" + +typedef struct exrate { + DateTime datetime; + int q, n; +} Exrate; + +int ExrateRead(Exrate *e, FILE *fp); +void ExratePrint(Exrate e); +Exrate ExrateEmpty(); +#endif diff --git a/Laboratorio 8/Esercizio 3/ExrateBST.c b/Laboratorio 8/Esercizio 3/ExrateBST.c new file mode 100644 index 0000000..0f44958 --- /dev/null +++ b/Laboratorio 8/Esercizio 3/ExrateBST.c @@ -0,0 +1,266 @@ +// Laboratorio 8 - Esercizio 3 - ExrateBST.c +// Matteo Schiff - s295565 + +#include +#include "ExrateBST.h" + +typedef struct node *link; +struct node +{ + Exrate exrate; + int N; + link left, right; +}; + +struct exrateBST +{ + link root; + link z; + int N; +}; + +static link createNode(Exrate exrate, link l, link r, int N) +{ + link new = malloc(sizeof(*new)); + new->exrate = exrate; + new->left = l; + new->right = r; + new->N = N; + return new; +} + +static link rotR(link n) +{ + link t = n->left; + n->left = t->right; + t->right = n; + t->N = n->N; + n->N = 1; + n->N += (n->left) ? n->left->N : 0; + n->N += (n->right) ? n->right->N : 0; + return t; +} + +static link rotL(link h) +{ + link t = h->right; + h->right = t->left; + t->left = h; + t->N = h->N; + h->N = 1; + h->N += (h->left) ? h->left->N : 0; + h->N += (h->right) ? h->right->N : 0; + return t; +} + +ExrateBST ExrateBSTCreate() +{ + ExrateBST new = malloc(sizeof(*new)); + new->z = createNode(ExrateEmpty(), NULL, NULL, 0); + new->root = new->z; + + return new; +} + +static void freeBST(link n, link z) +{ + if (n == z) + return; + + free(n->left); + free(n->right); + free(n); +} + +void ExrateBSTFree(ExrateBST ebst) +{ + freeBST(ebst->root, ebst->z); + free(ebst->z); + free(ebst); +} + +static link search(link n, DateTime dt, link z) +{ + if (n == z) + return z; + + int c = DateTimeCompare(dt, n->exrate.datetime); + if (c == 0) + return n; + if (c > 0) + return search(n->right, dt, z); + else + return search(n->left, dt, z); +} + +Exrate ExrateBSTSearch(ExrateBST ebst, DateTime dt) +{ + // nota: se search restituisce z, allora z,exrate è l'exrate nullo + return search(ebst->root, dt, ebst->z)->exrate; +} + +static void ExrateBSTInsertLeaf(ExrateBST ebst, Exrate exrate) +{ + if (ebst->root == ebst->z) + { + ebst->root = createNode(exrate, ebst->z, ebst->z, 1); + ebst->N++; + + return; + } + + link *n = &ebst->root; + while (*n != ebst->z) + { + (*n)->N++; + if (DateTimeCompare(exrate.datetime, (*n)->exrate.datetime) > 0) + { + + n = &(*n)->right; + } + else + { + n = &(*n)->left; + } + } + *n = createNode(exrate, ebst->z, ebst->z, 1); + ebst->N++; +} + +void ExrateBSTInsert(ExrateBST ebst, Exrate exrate) +{ + link node = search(ebst->root, exrate.datetime, ebst->z); + + if (node != ebst->z) + { + // Merge exrate + node->exrate.q = ((node->exrate.n * node->exrate.q) + (exrate.n * exrate.q)) / (node->exrate.n + exrate.n); + node->exrate.n += exrate.n; + } + else + { + ExrateBSTInsertLeaf(ebst, exrate); + } +} + +static void mergeR(ExrateBST dst, link r, link z) +{ + if (r == z) + return; + + mergeR(dst, r->left, z); + mergeR(dst, r->right, z); + ExrateBSTInsert(dst, r->exrate); +} + +void ExrateBSTMerge(ExrateBST dst, ExrateBST src) +{ + mergeR(dst, src->root, src->z); +} + +static void getMaxMinLengthR(link n, link z, int *min, int *max, int *counter) +{ + if (n == z) + { + if (*counter < *min) + *min = *counter; + if (*counter > *max) + *max = *counter; + return; + } + + (*counter)++; + getMaxMinLengthR(n->left, z, min, max, counter); + getMaxMinLengthR(n->right, z, min, max, counter); + (*counter)--; +} + +static int getMaxMinDiff(ExrateBST ebst) +{ + int counter = 0, min = ebst->N, max = 0; + getMaxMinLengthR(ebst->root, ebst->z, &min, &max, &counter); + + return max - min; +} + +link partR(link h, int r) +{ + int t = h->left->N; + if (t > r) + { + h->left = partR(h->left, r); + h = rotR(h); + } + if (t < r) + { + h->right = partR(h->right, r - t - 1); + h = rotL(h); + } + return h; +} + +static link balanceR(link h, link z) +{ + int r; + if (h == z) + return z; + r = (h->N + 1) / 2 - 1; + h = partR(h, r); + h->left = balanceR(h->left, z); + h->right = balanceR(h->right, z); + return h; +} + +void visitInOrderCheckInterval(link h, link z, DateTime dt1, DateTime dt2, int interval, Exrate *min, Exrate *max) { + if (h == z) + return; + + visitInOrderCheckInterval(h->left,z,dt1,dt2,interval,min,max); + + if (!interval || (DateTimeCompare(h->exrate.datetime, dt1) >= 0 && DateTimeCompare(h->exrate.datetime, dt2) <= 0)) { + if (h->exrate.q > max->q) + *max = h->exrate; + if (h->exrate.q < max->q) + *min = h->exrate; + } + + visitInOrderCheckInterval(h->right,z,dt1,dt2,interval,min,max); +} + +void ExrateBSTBalance(ExrateBST bst) +{ + // calcola la differenza (distanza root -> nodo massima) - (distanza root -> nodo minima) + int diff = getMaxMinDiff(bst); + + if (diff >= S) + { + printf("La differenza tra il cammino più corto e quello più lungo è di %d, bilancio l'albero...\n", diff); + bst->root = balanceR(bst->root, bst->z); + + diff = getMaxMinDiff(bst); + printf("Bilanciato, ora la differenza è di: %d\n", diff); + } + else + { + printf("La differenza tra il cammino più corto e quello più lungo è di %d, non è necessario bilanciare l'albero\n", diff); + } +} + +void ExrateBSTMinMaxW(ExrateBST bst, DateTime dt1, DateTime dt2, int interval) { + Exrate min, max; + min = max = bst->root->exrate; + visitInOrderCheckInterval(bst->root, bst->z, dt1, dt2, interval, &min, &max); + printf("Quotazione minima: "); + ExratePrint(min); + printf("Quotazione massima: "); + ExratePrint(max); +} + +void ExrateBSTMinMax(ExrateBST bst) { + DateTime empty; + ExrateBSTMinMaxW(bst, empty, empty, 0); +} + +void ExrateBSTMinMaxInInterval(ExrateBST bst, DateTime dt1, DateTime dt2) { + ExrateBSTMinMaxW(bst, dt1, dt2, 1); +} diff --git a/Laboratorio 8/Esercizio 3/ExrateBST.h b/Laboratorio 8/Esercizio 3/ExrateBST.h new file mode 100644 index 0000000..c04544b --- /dev/null +++ b/Laboratorio 8/Esercizio 3/ExrateBST.h @@ -0,0 +1,23 @@ +// Laboratorio 8 - Esercizio 3 - ExrateBST.h +// Matteo Schiff - s295565 + +#ifndef EXRATEBST_DEFINED +#define EXRATEBST_DEFINED + +#include "Exrate.h" +#include "Datetime.h" + +#define S 5 + +typedef struct exrateBST *ExrateBST; +ExrateBST ExrateBSTCreate(); +void ExrateBSTFree(ExrateBST ebst); +void ExrateBSTInsert(ExrateBST ebst, Exrate exrate); +void ExrateBSTMerge(ExrateBST dst, ExrateBST src); + +Exrate ExrateBSTSearch(ExrateBST ebst, DateTime dt); +void ExrateBSTBalance(ExrateBST bst); +void ExrateBSTMinMaxInInterval(ExrateBST bst, DateTime dt1, DateTime dt2); +void ExrateBSTMinMax(ExrateBST bst); + +#endif \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 3/F1.txt b/Laboratorio 8/Esercizio 3/F1.txt new file mode 100644 index 0000000..cfbb731 --- /dev/null +++ b/Laboratorio 8/Esercizio 3/F1.txt @@ -0,0 +1,11 @@ +3 +ABC001 4 +2018/01/01 00:00 100 3 +2018/01/01 00:01 78 1 +2018/01/01 00:02 345 9 +2018/01/01 00:03 13 1 +ABC002 2 +2018/01/01 00:00 244 23 +2018/01/01 00:01 190 56 +ABC003 1 +2018/01/02 00:00 1 1 diff --git a/Laboratorio 8/Esercizio 3/F2.txt b/Laboratorio 8/Esercizio 3/F2.txt new file mode 100644 index 0000000..292bcf3 --- /dev/null +++ b/Laboratorio 8/Esercizio 3/F2.txt @@ -0,0 +1,11 @@ +3 +ABC006 4 +2018/01/03 00:00 100 3 +2018/01/03 00:01 78 1 +2018/01/03 00:02 345 9 +2018/01/03 00:03 13 1 +ABC003 2 +2018/01/03 00:00 244 23 +2018/01/03 00:01 190 56 +ABC011 1 +2018/01/06 00:00 1 1 diff --git a/Laboratorio 8/Esercizio 3/F3.txt b/Laboratorio 8/Esercizio 3/F3.txt new file mode 100644 index 0000000..5994f5a --- /dev/null +++ b/Laboratorio 8/Esercizio 3/F3.txt @@ -0,0 +1,17 @@ +4 +ABC005 4 +2018/01/07 00:00 100 3 +2018/01/07 00:01 78 1 +2018/01/07 00:02 345 9 +2018/01/07 00:03 13 1 +ABC002 2 +2018/01/12 00:00 244 23 +2018/01/11 00:01 190 56 +ABC003 1 +2018/01/20 00:00 1 1 +ABC001 5 +2018/01/20 00:00 3 3 +2018/01/21 00:00 3 3 +2018/01/22 00:00 3 3 +2018/01/23 00:00 3 3 +2018/01/24 00:00 3 3 \ No newline at end of file diff --git a/Laboratorio 8/Esercizio 3/main.c b/Laboratorio 8/Esercizio 3/main.c new file mode 100644 index 0000000..f4d32a0 --- /dev/null +++ b/Laboratorio 8/Esercizio 3/main.c @@ -0,0 +1,180 @@ +// Laboratorio 8 - Esercizio 3 - main.c +// Matteo Schiff - s295565 + +#include +#include + +#include"AssetList.h" +#include"Asset.h" +#include"ExrateBST.h" + +#define MAX_LEN 30 + +const int MAXL = 100; + +typedef enum +{ + r_read, + r_select_asset, + r_get_quot_date, + r_get_quot_min_max_date, + r_get_min_max, + r_balance, + r_fine +} t_comandi; + +char *toLower(char *s) +{ + for (char *p = s; *p; p++) + *p = tolower(*p); + return s; +} + +t_comandi leggiComando() +{ + t_comandi c; + char cmd[MAXL]; + char tabella[7][30] = { + "leggi_file", "seleziona_asset", "quotazione_data", "quotazione_min_max_data", "quotazione_min_max","bilancia", "fine"}; + printf("comando (leggi_file, seleziona_asset, quotazione_data, quotazione_min_max_data, quotazione_min_max, bilancia, fine): "); + scanf("%s", cmd); + toLower(cmd); + c = r_read; + while (c < 7 && strcmp(cmd, tabella[c]) != 0) + c++; + return (c); +} + +void handleRead(AssetList assetList) { + FILE *fp; + char filename[MAX_LEN+1]; + int N; + + printf("Filename: "); + scanf("%s", filename); + + if ((fp = fopen(filename, "r")) == NULL) { + printf("ERROR opening input file\n"); + return; + } + + fscanf(fp, "%d", &N); + for (int i = 0; i < N; i++) { + Asset newAsset = AssetRead(fp); + AssetListInsert(assetList, newAsset); + } + + fclose(fp); +} + +void handleAssetSelection(AssetList assetList, Asset **selectedAsset) { + char title[MAX_LEN+1]; + + if (AssetListLength(assetList) == 0) + printf("Nessun asset selezionato\n"); + else { + AssetListPrint(assetList); + printf("Quale asset vuoi scegliere: "); + scanf("%s", title); + + if ((*selectedAsset = AssetListSearch(assetList, title)) == NULL) { + printf("Nessun asset trovato\n"); + } + } + +} + +void handleSingleExrateSearch(AssetList assetList, Asset *selectedAsset) { + Exrate dailyexrate; + + if (selectedAsset == NULL) + printf("Nessun asset selezionato\n"); + else { + DateTime dt; + printf("Data (yyyy/mm/dd): "); + DateRead(&dt, stdin); + dailyexrate = ExrateBSTSearch(AssetGetExrates(*selectedAsset), dt); + ExratePrint(dailyexrate); + } +} + +void handleMultiExrateSearch(AssetList assetList, Asset *selectedAsset) { + if (selectedAsset == NULL) + printf("Nessun asset selezionato\n"); + else { + ExrateBSTMinMax(AssetGetExrates(*selectedAsset)); + } + +} + +void handleMultiExrateSearchInterval(AssetList assetList, Asset *selectedAsset) { + if (selectedAsset == NULL) + printf("Nessun asset selezionato\n"); + else { + DateTime dt1; + DateTime dt2; + printf("Data inizio (yyyy/mm/dd): "); + DateRead(&dt1, stdin); + printf("Data fine (yyyy/mm/dd): "); + DateRead(&dt2, stdin); + + ExrateBSTMinMaxInInterval(AssetGetExrates(*selectedAsset), dt1, dt2); + } + +} + +void handleBalance(Asset *asset) { + if (asset == NULL) + printf("Nessun asset selezionato\n"); + else + ExrateBSTBalance(AssetGetExrates(*asset)); +} + +void menuParola(AssetList al) +{ + Asset *selected = NULL; + t_comandi comando; + int i, continua = 1; + while (continua) + { + comando = leggiComando(); + switch (comando) + { + case r_read: + handleRead(al); + break; + case r_select_asset: + handleAssetSelection(al, &selected); + break; + case r_get_quot_date: + handleSingleExrateSearch(al, selected); + break; + case r_get_quot_min_max_date: + handleMultiExrateSearchInterval(al, selected); + break; + case r_get_min_max: + handleMultiExrateSearch(al, selected); + break; + case r_balance: + handleBalance(selected); + break; + case r_fine: + continua = 0; + break; + default: + puts("Comando non valido\n"); + } + } +} + +int main(int argc, char const *argv[]) +{ + char filename[MAX_LEN]; + AssetList al = AssetListCreate(); + + menuParola(al); + + AssetListFree(al); + + return 0; +} diff --git a/Laboratorio 9/Esercizio 1/DAG.txt b/Laboratorio 9/Esercizio 1/DAG.txt new file mode 100644 index 0000000..25bc97f --- /dev/null +++ b/Laboratorio 9/Esercizio 1/DAG.txt @@ -0,0 +1,20 @@ +7 +A +B +C +D +E +F +G +A F 12 +A D 67 +A C 12 +A B 34 +B F 5 +B E 90 +C F 90 +C D 5 +D E 12 +E G 2 +E F 1 +G F 3 diff --git a/Laboratorio 9/Esercizio 1/Graph.c b/Laboratorio 9/Esercizio 1/Graph.c new file mode 100644 index 0000000..3962508 --- /dev/null +++ b/Laboratorio 9/Esercizio 1/Graph.c @@ -0,0 +1,414 @@ +// Laboratorio 9 - Esercizio 1 - Graph.c +// Matteo Schiff - s295565 + +#include +#include +#include +#include + +#include "Graph.h" +#include "ST.h" + +typedef struct node *link; +struct node +{ + int v; + int wt; + link next; +}; + +struct graph +{ + int V; + int E; + link *ladj; + link z; + ST tab; +}; + +static link newNode(int v, int wt, link next) +{ + link t = (link)malloc(sizeof(*t)); + t->v = v; + t->wt = wt; + t->next = next; + return t; +} + +static void freeList(link t, link z) +{ + link q, x = t; + if (t == z) + return; + + while (x != z) + { + q = x->next; + free(x); + x = q; + } +} + +static int searchList(link t, link z, int v) +{ + for (link x = t; x != z; x = x->next) + { + if (x->v == v) + return 1; + } + + return 0; +} + +static Edge EDGEcreate(int v, int w, int wt) +{ + Edge e; + e.v = v; + e.w = w; + e.wt = wt; + return e; +} + +void GRAPHedges(Graph G, Edge *a) +{ + int v, E = 0; + link t; + for (v = 0; v < G->V; v++) + for (t = G->ladj[v]; t != G->z; t = t->next) + a[E++] = EDGEcreate(v, t->v, t->wt); +} + +Graph GRAPHload(FILE *fin) +{ + int V, i, id1, id2, wt; + char label1[MAX_LEN + 1], label2[MAX_LEN + 1]; + Graph G; + fscanf(fin, "%d", &V); + G = GRAPHinit(V); + for (i = 0; i < V; i++) + { + fscanf(fin, "%s", label1); + STinsert(G->tab, label1); + } + while (fscanf(fin, "%s %s %d", label1, label2, &wt) == 3) + { + id1 = STsearch(G->tab, label1); + id2 = STsearch(G->tab, label2); + if (id1 >= 0 && id2 >= 0) + GRAPHinsertE(G, id1, id2, wt); + } + return G; +} + +void GRAPHstore(Graph G, FILE *fout) +{ + int i; + Edge *a; + a = malloc(G->E * sizeof(Edge)); + GRAPHedges(G, a); + fprintf(fout, "%d\n", G->V); + for (i = 0; i < G->V; i++) + fprintf(fout, "%s\n", STsearchByIndex(G->tab, i)); + for (i = 0; i < G->E; i++) + fprintf(fout, "%s %s %d\n", + STsearchByIndex(G->tab, a[i].v), + STsearchByIndex(G->tab, a[i].w), a[i].wt); + free(a); +} + +void GRAPHinsertE(Graph G, int v, int w, int wt) +{ + G->ladj[v] = newNode(w, wt, G->ladj[v]); + G->E++; +} + +void GRAPHremoveE(Graph G, int v, int w) +{ + link x, p; + for (x = G->ladj[v], p = NULL; x != G->z; p = x, x = x->next) + { + if (x->v == w) + { + if (x == G->ladj[v]) + G->ladj[v] = x->next; + else + p->next = x->next; + break; + } + } + G->E--; + free(x); +} + +static link *LISTinit(int V, link z) +{ + link *list = (link *)malloc(V * sizeof(link)); + for (int v = 0; v < V; v++) + list[v] = z; + + return list; +} + +Graph GRAPHinit(int V) +{ + Graph G = malloc(sizeof *G); + G->V = V; + G->E = 0; + G->z = newNode(-1, -1, NULL); + G->ladj = LISTinit(V, G->z); + G->tab = STinit(V); + return G; +} + +void GRAPHfree(Graph G) +{ + int i; + for (i = 0; i < G->V; i++) + { + freeList(G->ladj[i], G->z); + } + free(G->ladj); + free(G->z); + STfree(G->tab); + free(G); +} + +int GRAPHgetIndex(Graph G, char *item) +{ + int id; + id = STsearch(G->tab, item); + if (id == -1) + { + id = STinsert(G->tab, item); + G->V++; + } + return id; +} + +int GRAPHEdgeCount(Graph G) +{ + return G->E; +} + +// funzione che restituisce in `backEdges` tutti i vertici di tipo backward +void searchBackwardEdgesR(Graph G, Edge e, int *time, + int *pre, int *post, Edge *backEdges, int *backEdgesNum) +{ + pre[e.w] = (*time)++; + for (link t = G->ladj[e.w]; t != G->z; t = t->next) + if (pre[t->v] == -1) + searchBackwardEdgesR(G, EDGEcreate(e.w, t->v, t->wt), time, pre, post, backEdges, backEdgesNum); + else + { + if (post[t->v] == -1) + backEdges[(*backEdgesNum)++] = EDGEcreate(e.w, t->v, t->wt); + } + post[e.w] = (*time)++; +} + +void GRAPHFindCardMinDAG(Graph G, int *cardinality, Edge *edges) +{ + int *pre = (int *)malloc(G->V * sizeof(int)); + int *post = (int *)malloc(G->V * sizeof(int)); + Edge **backEdges = malloc(G->V * sizeof(Edge *)); + int *cards = (int *)malloc(G->V * sizeof(int)); + + for (int i = 0; i < G->V; i++) + { + backEdges[i] = malloc(G->E * sizeof(Edge)); + for (int j = 0; j < G->E; j++) + { + backEdges[i][j] = EDGEcreate(0, 0, 0); + } + } + + int minCard = -1; + + for (int i = 0; i < G->V; i++) + { + int time = 0; + cards[i] = 0; + for (int j = 0; j < G->V; j++) + { + pre[j] = -1; + post[j] = -1; + } + + // per rendere un grafo un DAG bisogna togliere tutti gli archi backward + searchBackwardEdgesR(G, EDGEcreate(i, i, 0), &time, pre, post, backEdges[i], &cards[i]); + for (int j = 0; j < G->V; j++) + if (pre[j] == -1) + searchBackwardEdgesR(G, EDGEcreate(j, j, 0), &time, pre, post, backEdges[i], &cards[i]); + + // inizio a memorizzare la cardinalità minima + if (cards[i] < minCard || minCard == -1) + { + minCard = cards[i]; + } + } + + free(post); + free(pre); + + int curWeight, idMaxWeight = 0, maxWeight = -1; + + if (minCard == 0) + { + puts("Il grafo è già un DAG, non si deve fare nulla"); + *cardinality = 0; + } + else + { + puts("Insiemi di archi da rimuovere con cardinalità minima: "); + for (int i = 0; i < G->V; i++) + { + curWeight = 0; + if (cards[i] != minCard) + continue; + + printf("{"); + for (int j = 0; j < G->E; j++) + { + if (backEdges[i][j].wt != 0) + { + curWeight += backEdges[i][j].wt; + printf(" (%s, %s, wt: %d)", STsearchByIndex(G->tab, backEdges[i][j].v), STsearchByIndex(G->tab, backEdges[i][j].w), backEdges[i][j].wt); + } + } + + // mentre stampo gli insiemi cerco l'insieme di peso massimo + if (curWeight > maxWeight) + { + maxWeight = curWeight; + idMaxWeight = i; + } + printf(" }\n"); + } + + printf("Insieme di archi da rimuovere a peso massimo:\n {"); + for (int i = 0; i < cards[idMaxWeight]; i++) + { + edges[i] = backEdges[idMaxWeight][i]; + printf(" (%s, %s, wt: %d)", STsearchByIndex(G->tab, backEdges[idMaxWeight][i].v), STsearchByIndex(G->tab, backEdges[idMaxWeight][i].w), backEdges[idMaxWeight][i].wt); + } + printf(" }\n"); + *cardinality = cards[idMaxWeight]; + } + + for (int i = 0; i < G->V; i++) + { + free(backEdges[i]); + } + free(backEdges); + free(cards); +} + +void GRAPHRemoveEdges(Graph G, Edge *edges, int N) +{ + for (int i = 0; i < N; i++) + GRAPHremoveE(G, edges[i].v, edges[i].w); +} + +static int GRAPHisSource(Graph G, int id) +{ + // un nodo è sorgente se nessun arco punta a tale nodo + for (int v = 0; v < G->V; v++) + { + for (link t = G->ladj[v]; t != G->z; t = t->next) + { + if (t->v == id) + { + // ho trovato un arco che punta al nodo + return 0; + } + } + } + + return 1; +} + +void sortTopologicalR(Graph G, int w, int *time, + int *pre, int *post, int *orderedVertex, int *cnt) +{ + pre[w] = (*time)++; + for (link t = G->ladj[w]; t != G->z; t = t->next) + if (pre[t->v] == -1) + sortTopologicalR(G, t->v, time, pre, post, orderedVertex, cnt); + post[w] = (*time)++; + orderedVertex[(*cnt)++] = w; +} + +void sortTopological(Graph G, int start, int *orderedVertex) +{ + int time = 0, cnt = 0; + int *pre = (int *)malloc(G->V * sizeof(int)); + int *post = (int *)malloc(G->V * sizeof(int)); + for (int j = 0; j < G->V; j++) + { + pre[j] = -1; + post[j] = -1; + } + sortTopologicalR(G, start, &time, pre, post, orderedVertex, &cnt); + free(post); + free(pre); +} + +void GRAPHmaxPathFromSource(Graph G) +{ + link t; + + int *distances = (int *)malloc(G->V * sizeof(int)); + int *st = (int *)malloc(G->V * sizeof(int)); + int *topSorted = (int *)malloc(G->V * sizeof(int)); + + for (int i = 0; i < G->V; i++) + { + if (GRAPHisSource(G, i)) + { + // ordinamento topologico dei vertici a partire dalla sorgente i + sortTopological(G, i, topSorted); + for (int j = 0; j < G->V; j++) + { + distances[j] = INT_MIN; + st[j] = -1; + } + distances[i] = 0; + st[i] = i; + + for (int j = G->V-1; j >=0; j--) + { + int k = topSorted[j]; + for (t = G->ladj[k]; t != G->z; t = t->next) + { + // aggiorno le distanze se ho trovato un cammino più lungo + if (distances[t->v] < distances[k] + t->wt) + { + st[t->v] = k; + distances[t->v] = distances[k] + t->wt; + } + } + } + + // stampo per ogni vertice il cammino massimo + for (int j = 0; j < G->V; j++) + { + int k = j; + if (j != i) + { + printf("Cammino massimo dalla sorgente %s al nodo %s:\n", STsearchByIndex(G->tab, i), STsearchByIndex(G->tab, j)); + printf("%s", STsearchByIndex(G->tab, k)); + while (k != i) + { + printf(" <- %s", STsearchByIndex(G->tab, st[k])); + k = st[k]; + } + printf("\nPeso del cammino: %d\n", distances[j]); + } + } + } + } + + free(distances); + free(topSorted); + free(st); +} diff --git a/Laboratorio 9/Esercizio 1/Graph.h b/Laboratorio 9/Esercizio 1/Graph.h new file mode 100644 index 0000000..d7a9c30 --- /dev/null +++ b/Laboratorio 9/Esercizio 1/Graph.h @@ -0,0 +1,26 @@ +// Laboratorio 9 - Esercizio 1 - Graph.h +// Matteo Schiff - s295565 + +#ifndef GRAPH_DEFINED +#define GRAPH_DEFINED + +#include + +typedef struct edge +{ + int v; + int w; + int wt; +} Edge; +typedef struct graph *Graph; +Graph GRAPHinit(int V); +void GRAPHfree(Graph G); +Graph GRAPHload(FILE *fin); +void GRAPHstore(Graph G, FILE *fout); +int GRAPHgetIndex(Graph G, char * item); +void GRAPHinsertE(Graph G, int v, int w, int wt); +int GRAPHEdgeCount(Graph G); +void GRAPHFindCardMinDAG(Graph G, int *cardinality, Edge *edges); +void GRAPHRemoveEdges(Graph G, Edge *edges, int N); +void GRAPHmaxPathFromSource(Graph G); +#endif \ No newline at end of file diff --git a/Laboratorio 9/Esercizio 1/GraphOld.c b/Laboratorio 9/Esercizio 1/GraphOld.c new file mode 100644 index 0000000..975c3e4 --- /dev/null +++ b/Laboratorio 9/Esercizio 1/GraphOld.c @@ -0,0 +1,385 @@ +// Laboratorio 9 - Esercizio 1 - Graph.c +// Matteo Schiff - s295565 + +#include +#include +#include +#include + +#include "Graph.h" +#include "ST.h" + +typedef struct node *link; +struct node +{ + int v; + int wt; + link next; +}; + +struct graph +{ + int V; + int E; + link *ladj; + link z; + ST tab; +}; + +static link newNode(int v, int wt, link next) +{ + link t = (link)malloc(sizeof(*t)); + t->v = v; + t->wt = wt; + t->next = next; + return t; +} + +static void freeList(link t, link z) +{ + link q, x = t; + if (t == z) + return; + + while (x != z) + { + q = x->next; + free(x); + x = q; + } +} + +static int searchList(link t, link z, int v) +{ + for (link x = t; x != z; x = x->next) + { + if (x->v == v) + return 1; + } + + return 0; +} + +static Edge EDGEcreate(int v, int w, int wt) +{ + Edge e; + e.v = v; + e.w = w; + e.wt = wt; + return e; +} + +void GRAPHedges(Graph G, Edge *a) +{ + int v, E = 0; + link t; + for (v = 0; v < G->V; v++) + for (t = G->ladj[v]; t != G->z; t = t->next) + a[E++] = EDGEcreate(v, t->v, t->wt); +} + +Graph GRAPHload(FILE *fin) +{ + int V, i, id1, id2, wt; + char label1[MAX_LEN + 1], label2[MAX_LEN + 1]; + Graph G; + fscanf(fin, "%d", &V); + G = GRAPHinit(V); + for (i = 0; i < V; i++) + { + fscanf(fin, "%s", label1); + STinsert(G->tab, label1); + } + while (fscanf(fin, "%s %s %d", label1, label2, &wt) == 3) + { + id1 = STsearch(G->tab, label1); + id2 = STsearch(G->tab, label2); + if (id1 >= 0 && id2 >= 0) + GRAPHinsertE(G, id1, id2, wt); + } + return G; +} + +void GRAPHstore(Graph G, FILE *fout) +{ + int i; + Edge *a; + a = malloc(G->E * sizeof(Edge)); + GRAPHedges(G, a); + fprintf(fout, "%d\n", G->V); + for (i = 0; i < G->V; i++) + fprintf(fout, "%s\n", STsearchByIndex(G->tab, i)); + for (i = 0; i < G->E; i++) + fprintf(fout, "%s %s %d\n", + STsearchByIndex(G->tab, a[i].v), + STsearchByIndex(G->tab, a[i].w), a[i].wt); +} + +void GRAPHinsertE(Graph G, int v, int w, int wt) +{ + G->ladj[v] = newNode(w, wt, G->ladj[v]); + G->E++; +} + +void GRAPHremoveE(Graph G, int v, int w) +{ + link x, p; + for (x = G->ladj[v], p = NULL; x != G->z; p = x, x = x->next) + { + if (x->v == w) + { + if (x == G->ladj[v]) + G->ladj[v] = x->next; + else + p->next = x->next; + break; + } + } + G->E--; + free(x); +} + +static link *LISTinit(int V, link z) +{ + link *list = (link *)malloc(V * sizeof(link)); + for (int v = 0; v < V; v++) + list[v] = z; + + return list; +} + +Graph GRAPHinit(int V) +{ + Graph G = malloc(sizeof *G); + G->V = V; + G->E = 0; + G->z = newNode(-1, -1, NULL); + G->ladj = LISTinit(V, G->z); + G->tab = STinit(V); + return G; +} + +void GRAPHfree(Graph G) +{ + int i; + for (i = 0; i < G->V; i++) + { + freeList(G->ladj[i], G->z); + } + free(G->ladj); + free(G->z); + STfree(G->tab); + free(G); +} + +int GRAPHgetIndex(Graph G, char *item) +{ + int id; + id = STsearch(G->tab, item); + if (id == -1) + { + id = STinsert(G->tab, item); + G->V++; + } + return id; +} + +int GRAPHEdgeCount(Graph G) +{ + return G->E; +} + +// funzione che restituisce in `backEdges` tutti i vertici di tipo backward +void searchBackwardEdgesR(Graph G, Edge e, int *time, + int *pre, int *post, Edge *backEdges, int *backEdgesNum) +{ + pre[e.w] = (*time)++; + for (link t = G->ladj[e.w]; t != G->z; t = t->next) + if (pre[t->v] == -1) + searchBackwardEdgesR(G, EDGEcreate(e.w, t->v, t->wt), time, pre, post, backEdges, backEdgesNum); + else + { + if (post[t->v] == -1) + backEdges[(*backEdgesNum)++] = EDGEcreate(e.w, t->v, t->wt); + } + post[e.w] = (*time)++; +} + +void GRAPHFindCardMinDAG(Graph G, int *cardinality, Edge *edges) +{ + int *pre = (int *)malloc(G->V * sizeof(int)); + int *post = (int *)malloc(G->V * sizeof(int)); + Edge **backEdges = malloc(G->V * sizeof(Edge *)); + int *cards = (int *)malloc(G->V * sizeof(int)); + + for (int i = 0; i < G->V; i++) + { + backEdges[i] = malloc(G->E * sizeof(Edge)); + for (int j = 0; j < G->E; j++) + { + backEdges[i][j] = EDGEcreate(0, 0, 0); + } + } + + int minCard = -1; + + for (int i = 0; i < G->V; i++) + { + int time = 0; + cards[i] = 0; + for (int j = 0; j < G->V; j++) + { + pre[j] = -1; + post[j] = -1; + } + + // per rendere un grafo un DAG bisogna togliere tutti gli archi backward + searchBackwardEdgesR(G, EDGEcreate(i, i, 0), &time, pre, post, backEdges[i], &cards[i]); + for (int j = 0; j < G->V; j++) + if (pre[j] == -1) + searchBackwardEdgesR(G, EDGEcreate(j, j, 0), &time, pre, post, backEdges[i], &cards[i]); + + // inizio a memorizzare la cardinalità minima + if (cards[i] < minCard || minCard == -1) + { + minCard = cards[i]; + } + } + + free(post); + free(pre); + + int curWeight, idMaxWeight = 0, maxWeight = -1; + + if (minCard == 0) + { + puts("Il grafo è già un DAG, non si deve fare nulla"); + *cardinality = 0; + } + else + { + puts("Insiemi di archi da rimuovere con cardinalità minima: "); + for (int i = 0; i < G->V; i++) + { + curWeight = 0; + if (cards[i] != minCard) + continue; + + printf("{"); + for (int j = 0; j < G->E; j++) + { + if (backEdges[i][j].wt != 0) + { + curWeight += backEdges[i][j].wt; + printf(" (%s, %s, wt: %d)", STsearchByIndex(G->tab, backEdges[i][j].v), STsearchByIndex(G->tab, backEdges[i][j].w), backEdges[i][j].wt); + } + } + + // mentre stampo gli insiemi cerco l'insieme di peso massimo + if (curWeight > maxWeight) + { + maxWeight = curWeight; + idMaxWeight = i; + } + printf(" }\n"); + } + + printf("Insieme di archi da rimuovere a peso massimo:\n {"); + for (int i = 0; i < cards[idMaxWeight]; i++) + { + edges[i] = backEdges[idMaxWeight][i]; + printf(" (%s, %s, wt: %d)", STsearchByIndex(G->tab, backEdges[idMaxWeight][i].v), STsearchByIndex(G->tab, backEdges[idMaxWeight][i].w), backEdges[idMaxWeight][i].wt); + } + printf(" }\n"); + *cardinality = cards[idMaxWeight]; + } + + for (int i = 0; i < G->V; i++) + { + free(backEdges[i]); + } + free(backEdges); + free(cards); +} + +void GRAPHRemoveEdges(Graph G, Edge *edges, int N) +{ + for (int i = 0; i < N; i++) + GRAPHremoveE(G, edges[i].v, edges[i].w); +} + +static int GRAPHisSource(Graph G, int id) +{ + // un nodo è sorgente se nessun arco punta a tale nodo + for (int v = 0; v < G->V; v++) + { + for (link t = G->ladj[v]; t != G->z; t = t->next) + { + if (t->v == id) + { + // ho trovato un arco che punta al nodo + return 0; + } + } + } + + return 1; +} + +void GRAPHmaxPathFromSource(Graph G) +{ + link t; + + int *distances = (int *)malloc(G->V * sizeof(int)); + int *st = (int *)malloc(G->V * sizeof(int)); + + for (int i = 0; i < G->V; i++) + { + if (GRAPHisSource(G, i)) + { + for (int j = 0; j < G->V; j++) + { + distances[j] = INT_MIN; + st[j] = -1; + } + distances[i] = 0; + st[i] = i; + + for (int j = 0; j < G->V - 1; j++) + { + for (int k = 0; k < G->V; k++) + { + for (t = G->ladj[k]; t != G->z; t = t->next) + { + // aggiorno le distanze se ho trovato un cammino più lungo + if (distances[t->v] < distances[k] + t->wt) + { + st[t->v] = k; + distances[t->v] = distances[k] + t->wt; + } + } + } + } + + // stampo per ogni vertice il cammino massimo + for (int j = 0; j < G->V; j++) + { + int k = j; + if (j != i) + { + printf("Cammino massimo dalla sorgente %s al nodo %s:\n", STsearchByIndex(G->tab, i), STsearchByIndex(G->tab, j)); + printf("%s", STsearchByIndex(G->tab, k)); + while (k != i) + { + printf(" <- %s", STsearchByIndex(G->tab, st[k])); + k = st[k]; + } + printf("\nPeso del cammino: %d\n", distances[j]); + } + } + } + } + + free(distances); + free(st); +} diff --git a/Laboratorio 9/Esercizio 1/ST.c b/Laboratorio 9/Esercizio 1/ST.c new file mode 100644 index 0000000..4b386db --- /dev/null +++ b/Laboratorio 9/Esercizio 1/ST.c @@ -0,0 +1,61 @@ +// Laboratorio 9 - Esercizio 1 - ST.c +// Matteo Schiff - s295565 + +#include +#include +#include + +#include "ST.h" + +struct st { + char **table; + int N; + int maxN; +}; + +ST STinit(int N) { + ST st = malloc(sizeof(*st)); + + st->table = malloc(N * sizeof(char *)); + for (int i = 0; i < N; i++) { + st->table[i] = (char *)malloc(MAX_LEN+1*sizeof(char)); + } + st->N = 0; + st->maxN = N; + + return st; +} + +void STfree(ST st) { + free(st->table); + free(st); +} + +int STinsert(ST st, char * label) { + if (st->N == st->maxN) { + printf("Errore, spazio esaurito nella ST\n"); + return -1; + } + + strncpy(st->table[st->N++], label, MAX_LEN+1); + return st->N-1; +} + +char * STsearchByIndex(ST st, int index) { + if (index >= st->N) + return NULL; + + return st->table[index]; +} + +int STsearch(ST st, char * label) { + for (int i = 0; i < st->N; i++) { + if (strcmp(label, st->table[i]) == 0) + return i; + } + return -1; +} + +int STcount(ST st) { + return st->N; +} \ No newline at end of file diff --git a/Laboratorio 9/Esercizio 1/ST.h b/Laboratorio 9/Esercizio 1/ST.h new file mode 100644 index 0000000..485af6d --- /dev/null +++ b/Laboratorio 9/Esercizio 1/ST.h @@ -0,0 +1,20 @@ +// Laboratorio 9 - Esercizio 1 - ST.h +// Matteo Schiff - s295565 + +#ifndef ST_DEFINED +#define ST_DEFINED +#define MAX_LEN 30 + +typedef struct st *ST; + +ST STinit(int N); +void STfree(ST st); + +int STinsert(ST st, char * label); + +char * STsearchByIndex(ST st, int index); +int STsearch(ST st, char * label); + +int STcount(ST st); + +#endif \ No newline at end of file diff --git a/Laboratorio 9/Esercizio 1/grafo1.txt b/Laboratorio 9/Esercizio 1/grafo1.txt new file mode 100644 index 0000000..98a2794 --- /dev/null +++ b/Laboratorio 9/Esercizio 1/grafo1.txt @@ -0,0 +1,9 @@ +4 +A +B +C +D +A B 1 +A C 1 +B C 1 +C D 1 diff --git a/Laboratorio 9/Esercizio 1/grafo2.txt b/Laboratorio 9/Esercizio 1/grafo2.txt new file mode 100644 index 0000000..90832b3 --- /dev/null +++ b/Laboratorio 9/Esercizio 1/grafo2.txt @@ -0,0 +1,9 @@ +4 +A +B +C +D +A B 34 +B C 90 +C D 5 +D A 4 diff --git a/Laboratorio 9/Esercizio 1/grafo3.txt b/Laboratorio 9/Esercizio 1/grafo3.txt new file mode 100644 index 0000000..fb9470c --- /dev/null +++ b/Laboratorio 9/Esercizio 1/grafo3.txt @@ -0,0 +1,22 @@ +7 +A +B +C +D +E +F +G +A B 34 +A C 12 +A D 67 +A E 45 +A F 12 +B E 90 +B F 5 +C D 5 +C F 90 +D E 12 +D G 91 +E F 1 +E G 2 +F G 3 \ No newline at end of file diff --git a/Laboratorio 9/Esercizio 1/grafo4.txt b/Laboratorio 9/Esercizio 1/grafo4.txt new file mode 100644 index 0000000..6d71d06 --- /dev/null +++ b/Laboratorio 9/Esercizio 1/grafo4.txt @@ -0,0 +1,22 @@ +7 +A +B +C +D +E +F +G +A B 34 +A C 12 +A D 67 +E A 45 +A F 12 +B E 90 +B F 5 +C D 5 +C F 90 +D E 12 +G D 91 +E F 1 +E G 2 +G F 3 diff --git a/Laboratorio 9/Esercizio 1/main.c b/Laboratorio 9/Esercizio 1/main.c new file mode 100644 index 0000000..fec6f96 --- /dev/null +++ b/Laboratorio 9/Esercizio 1/main.c @@ -0,0 +1,41 @@ +// Laboratorio 9 - Esercizio 1 - main.c +// Matteo Schiff - s295565 + +#include + +#include"Graph.h" + +int main(int argc, char const *argv[]) +{ + FILE * fp_read; + Graph G; + if (argc < 1) { + puts("Specifica il file tra gli argomenti"); + return 1; + } + + if ((fp_read = fopen(argv[1], "r")) == NULL) + { + puts("Impossibile aprire il file"); + return 1; + } + G = GRAPHload(fp_read); + fclose(fp_read); + + Edge *edgesToRemove = malloc(GRAPHEdgeCount(G) * sizeof(Edge)); + int cardinality; + GRAPHFindCardMinDAG(G, &cardinality, edgesToRemove); + if (cardinality != 0) { + GRAPHRemoveEdges(G, edgesToRemove, cardinality); + + // Salvo il DAG su file + FILE * fp_write = fopen("DAG.txt", "w"); + GRAPHstore(G, fp_write); + fclose(fp_write); + } + GRAPHmaxPathFromSource(G); + + GRAPHfree(G); + + return 0; +}