1
0

feat: Initial commit

This commit is contained in:
2024-03-22 17:37:24 +01:00
parent 4288bd63a1
commit 6732a7a166
120 changed files with 9620 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
// Laboratorio 8 - Esercizio 1 - Elementi.c
// Matteo Schiff - s295565
#include<stdio.h>
#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;
}

View File

@@ -0,0 +1,25 @@
// Laboratorio 8 - Esercizio 1 - Elementi.h
// Matteo Schiff - s295565
#ifndef ELEM_H_DEFINED
#define ELEM_H_DEFINED
#include<stdbool.h>
#include<stdio.h>
#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

View File

@@ -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

View File

@@ -0,0 +1,345 @@
// Laboratorio 8 - Esercizio 1 - main.c
// Matteo Schiff - s295565
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#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;
}

View File

@@ -0,0 +1,297 @@
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#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;
}

View File

@@ -0,0 +1,376 @@
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#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;
}

View File

@@ -0,0 +1,301 @@
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#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;
}

View File

@@ -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

View File

@@ -0,0 +1,316 @@
// Laboratorio 8 - Esercizio 2 - Graph.c
// Matteo Schiff - s295565
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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 \"<nome> <subnet>\"");
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);
}

View File

@@ -0,0 +1,26 @@
// Laboratorio 8 - Esercizio 2 - Graph.h
// Matteo Schiff - s295565
#ifndef GRAPH_DEFINED
#define GRAPH_DEFINED
#include<stdio.h>
#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

View File

@@ -0,0 +1,37 @@
// Laboratorio 8 - Esercizio 2 - Item.c
// Matteo Schiff - s295565
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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);
}

View File

@@ -0,0 +1,23 @@
// Laboratorio 8 - Esercizio 2 - Item.h
// Matteo Schiff - s295565
#ifndef ITEM_DEFINED
#define ITEM_DEFINED
#include <stdio.h>
#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

View File

@@ -0,0 +1,61 @@
// Laboratorio 8 - Esercizio 2 - ST.c
// Matteo Schiff - s295565
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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;
}

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,92 @@
// Laboratorio 8 - Esercizio 2 - main.c
// Matteo Schiff - s295565
#include<ctype.h>
#include<string.h>
#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;
}

View File

@@ -0,0 +1,53 @@
// Laboratorio 8 - Esercizio 3 - Asset.c
// Matteo Schiff - s295565
#include <stdlib.h>
#include <string.h>
#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);
}

View File

@@ -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

View File

@@ -0,0 +1,113 @@
// Laboratorio 8 - Esercizio 3 - AssetList.c
// Matteo Schiff - s295565
#include <stdlib.h>
#include <string.h>
#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++;
}

View File

@@ -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

View File

@@ -0,0 +1,36 @@
// Laboratorio 8 - Esercizio 3 - Datetime.c
// Matteo Schiff - s295565
#include <stdbool.h>
#include <stdio.h>
#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;
}

View File

@@ -0,0 +1,19 @@
// Laboratorio 8 - Esercizio 3 - Datetime.h
// Matteo Schiff - s295565
#ifndef DATETIME_DEFINED
#define DATETIME_DEFINED
#include <stdio.h>
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

View File

@@ -0,0 +1,36 @@
// Laboratorio 8 - Esercizio 3 - Exrate.c
// Matteo Schiff - s295565
#include <stdio.h>
#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;
}

View File

@@ -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

View File

@@ -0,0 +1,266 @@
// Laboratorio 8 - Esercizio 3 - ExrateBST.c
// Matteo Schiff - s295565
#include <stdlib.h>
#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);
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -0,0 +1,180 @@
// Laboratorio 8 - Esercizio 3 - main.c
// Matteo Schiff - s295565
#include<ctype.h>
#include<string.h>
#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;
}