From 96abb3e2d0fb2b1f7419b93d1908208a3db91f3b Mon Sep 17 00:00:00 2001 From: Karl_FRAM Date: Wed, 21 Oct 2026 11:30:16 +0200 Subject: [PATCH 1/2] EXO 4 - optimisation F3 --- banque.c | 664 +++++++++++++++++++++++++++---------------------------- 1 file changed, 332 insertions(+), 332 deletions(-) diff --git a/banque.c b/banque.c index e4783a6..6126447 100644 --- a/banque.c +++ b/banque.c @@ -1,332 +1,332 @@ -/* - * R5.A.04 - Qualité Algorithmique - * TD Complexité algorithmique : analyse des transactions d'une banque - * - * Le programme génère des transactions pseudo-aléatoires (toujours les - * mêmes, grâce à une graine fixe), puis calcule plusieurs indicateurs - * et produit un rapport dans rapport.txt. - * - * L'empreinte affichée à la fin doit rester IDENTIQUE après vos - * optimisations : elle prouve que le résultat n'a pas changé. - * - * Interdit : modifier les constantes, la génération des données, - * le format du rapport, ou écrire les résultats « en dur ». - * - * Compilation : gcc -O2 banque.c -o banque - * Profiling : gcc -O0 -g -pg banque.c -o banque && ./banque && gprof ./banque gmon.out - */ - -#include -#include - -#define NB_TRANSACTIONS 30000 -#define NB_CLIENTS 2000 -#define NB_JOURS 1000 -#define NB_REQUETES 30000 -#define MONTANT_MONNAIE 400 -#define GRAINE 20261020UL - -typedef struct { - int id; - int client; - int jour; - long montant; /* en centimes, négatif pour un débit */ -} Transaction; - -/* ------------------------------------------------------------------ */ -/* Données (ne pas modifier) */ -/* ------------------------------------------------------------------ */ - -static unsigned long etat_alea = GRAINE; - -unsigned long alea(void) -{ - etat_alea = etat_alea * 6364136223846793005UL + 1442695040888963407UL; - return etat_alea >> 33; -} - -Transaction *generer_transactions(int n) -{ - Transaction *t = malloc(n * sizeof(Transaction)); - for (int i = 0; i < n; i++) { - t[i].id = i; - t[i].client = alea() % NB_CLIENTS; - t[i].jour = alea() % NB_JOURS; - if (i > 0 && alea() % 20 == 0) - t[i].montant = -t[alea() % i].montant; /* opération inverse */ - else - t[i].montant = (long)(alea() % 100001) - 50000; - } - for (int i = n - 1; i > 0; i--) { /* mélange des id */ - int j = alea() % (i + 1); - int tmp = t[i].id; - t[i].id = t[j].id; - t[j].id = tmp; - } - return t; -} - -/* ------------------------------------------------------------------ */ -/* Fonctions à analyser et à optimiser */ -/* ------------------------------------------------------------------ */ - -/* F1 : trie les transactions par montant croissant, puis par id */ -void trier_par_montant(Transaction *t, int n) -{ - for (int i = 1; i < n; i++) { - Transaction cle = t[i]; - int j = i - 1; - while (j >= 0 && (t[j].montant > cle.montant || - (t[j].montant == cle.montant && t[j].id > cle.id))) { - t[j + 1] = t[j]; - j--; - } - t[j + 1] = cle; - } -} - -/* F2 : nombre de clients ayant au moins une transaction */ -int nb_clients_distincts(const Transaction *t, int n) -{ - int nb = 0; - for (int i = 0; i < n; i++) { - int deja_vu = 0; - for (int j = 0; j < i; j++) { - if (t[j].client == t[i].client) { - deja_vu = 1; - break; - } - } - if (!deja_vu) - nb++; - } - return nb; -} - -/* F3 : solde total de chaque client */ -void total_par_client(const Transaction *t, int n, long *totaux) -{ - for (int c = 0; c < NB_CLIENTS; c++) { - totaux[c] = 0; - for (int i = 0; i < n; i++) - if (t[i].client == c) - totaux[c] += t[i].montant; - } -} - -/* F4 : solde total de chaque jour */ -void total_par_jour(const Transaction *t, int n, long *totaux) -{ - for (int j = 0; j < NB_JOURS; j++) { - totaux[j] = 0; - for (int i = 0; i < n; i++) - if (t[i].jour == j) - totaux[j] += t[i].montant; - } -} - -/* F5 : période de jours consécutifs dont la somme des soldes est maximale */ -long meilleure_periode(const long *totaux, int nb_jours, int *debut, int *fin) -{ - long meilleur = totaux[0]; - *debut = 0; - *fin = 0; - for (int i = 0; i < nb_jours; i++) { - for (int j = i; j < nb_jours; j++) { - long somme = 0; - for (int k = i; k <= j; k++) - somme += totaux[k]; - if (somme > meilleur) { - meilleur = somme; - *debut = i; - *fin = j; - } - } - } - return meilleur; -} - -/* F6 : retrouve une transaction à partir de son id */ -const Transaction *rechercher_par_id(const Transaction *t, int n, int id) -{ - for (int i = 0; i < n; i++) - if (t[i].id == id) - return &t[i]; - return NULL; -} - -/* F7 : nombre de paires de transactions de montants opposés (a + b = 0) */ -long nb_paires_opposees(const Transaction *t, int n) -{ - long nb = 0; - for (int i = 0; i < n; i++) - for (int j = i + 1; j < n; j++) - if (t[i].montant + t[j].montant == 0) - nb++; - return nb; -} - -/* F8 : nombre de façons de rendre une somme avec les pièces disponibles */ -static const int PIECES[] = {1, 2, 5, 10, 20, 50, 100, 200}; -#define NB_PIECES 8 - -long nb_facons_rendre(int somme, int nb_pieces) -{ - if (somme == 0) - return 1; - if (somme < 0 || nb_pieces == 0) - return 0; - return nb_facons_rendre(somme - PIECES[nb_pieces - 1], nb_pieces) + - nb_facons_rendre(somme, nb_pieces - 1); -} - -/* F9 : catégorie d'une transaction (pour les statistiques) */ -int categorie(const Transaction *t) -{ - if (t->montant < 0) { - if (t->montant < -20000) { - if (t->jour % 7 == 5 || t->jour % 7 == 6) - return 1; - else - return 2; - } else if (t->montant < -5000) { - return 3; - } else { - if (t->client % 10 == 0) - return 4; - return 5; - } - } else if (t->montant == 0) { - return 0; - } else { - if (t->montant > 30000) { - if (t->client % 10 == 0 && t->jour % 7 < 5) - return 6; - return 7; - } else if (t->montant > 10000) { - return 8; - } else if (t->montant > 1000) { - if (t->jour % 30 == 0) - return 9; - return 10; - } - return 11; - } -} - -/* F10 : ajoute une ligne à la fin du rapport */ -int longueur(const char *s) -{ - int n = 0; - while (s[n] != '\0') - n++; - return n; -} - -void ajouter_ligne(char *rapport, const char *ligne) -{ - int fin = longueur(rapport); - int i = 0; - while (ligne[i] != '\0') { - rapport[fin + i] = ligne[i]; - i++; - } - rapport[fin + i] = '\0'; -} - -/* ------------------------------------------------------------------ */ -/* Programme principal (à adapter si vous changez les signatures) */ -/* ------------------------------------------------------------------ */ - -unsigned long empreinte(const char *s) -{ - unsigned long h = 1469598103934665603UL; - for (int i = 0; s[i] != '\0'; i++) { - h ^= (unsigned char)s[i]; - h *= 1099511628211UL; - } - return h; -} - -int main(void) -{ - Transaction *t = generer_transactions(NB_TRANSACTIONS); - char *rapport = malloc(1 << 20); - char ligne[128]; - rapport[0] = '\0'; - - /* recherches par id, dans l'ordre d'origine */ - long somme_requetes = 0; - unsigned long etat = 12345; - for (int q = 0; q < NB_REQUETES; q++) { - etat = etat * 1103515245UL + 12345UL; - const Transaction *r = rechercher_par_id(t, NB_TRANSACTIONS, (int)((etat >> 8) % NB_TRANSACTIONS)); - if (r != NULL) - somme_requetes += r->montant; - } - - int nb_clients = nb_clients_distincts(t, NB_TRANSACTIONS); - - static long totaux_clients[NB_CLIENTS]; - total_par_client(t, NB_TRANSACTIONS, totaux_clients); - - static long totaux_jours[NB_JOURS]; - total_par_jour(t, NB_TRANSACTIONS, totaux_jours); - int debut, fin; - long meilleure = meilleure_periode(totaux_jours, NB_JOURS, &debut, &fin); - - long nb_paires = nb_paires_opposees(t, NB_TRANSACTIONS); - - int categories[12] = {0}; - for (int i = 0; i < NB_TRANSACTIONS; i++) - categories[categorie(&t[i])]++; - - trier_par_montant(t, NB_TRANSACTIONS); - - long nb_facons = nb_facons_rendre(MONTANT_MONNAIE, NB_PIECES); - - /* rapport */ - snprintf(ligne, sizeof(ligne), "clients distincts;%d\n", nb_clients); - ajouter_ligne(rapport, ligne); - snprintf(ligne, sizeof(ligne), "somme des requetes;%ld\n", somme_requetes); - ajouter_ligne(rapport, ligne); - snprintf(ligne, sizeof(ligne), "meilleure periode;%d;%d;%ld\n", debut, fin, meilleure); - ajouter_ligne(rapport, ligne); - snprintf(ligne, sizeof(ligne), "paires opposees;%ld\n", nb_paires); - ajouter_ligne(rapport, ligne); - snprintf(ligne, sizeof(ligne), "facons de rendre %d;%ld\n", MONTANT_MONNAIE, nb_facons); - ajouter_ligne(rapport, ligne); - for (int c = 0; c < 12; c++) { - snprintf(ligne, sizeof(ligne), "categorie;%d;%d\n", c, categories[c]); - ajouter_ligne(rapport, ligne); - } - for (int c = 0; c < NB_CLIENTS; c++) { - snprintf(ligne, sizeof(ligne), "client;%d;%ld\n", c, totaux_clients[c]); - ajouter_ligne(rapport, ligne); - } - for (int j = 0; j < NB_JOURS; j++) { - snprintf(ligne, sizeof(ligne), "jour;%d;%ld\n", j, totaux_jours[j]); - ajouter_ligne(rapport, ligne); - } - for (int i = 0; i < NB_TRANSACTIONS; i += 10) { - snprintf(ligne, sizeof(ligne), "rang;%d;%d;%ld\n", i, t[i].id, t[i].montant); - ajouter_ligne(rapport, ligne); - } - - FILE *f = fopen("rapport.txt", "w"); - if (f != NULL) { - fputs(rapport, f); - fclose(f); - } - - printf("Clients distincts : %d\n", nb_clients); - printf("Somme des requêtes : %ld\n", somme_requetes); - printf("Meilleure période : jours %d à %d (%ld)\n", debut, fin, meilleure); - printf("Paires opposées : %ld\n", nb_paires); - printf("Façons de rendre %d : %ld\n", MONTANT_MONNAIE, nb_facons); - printf("Empreinte : %016lx\n", empreinte(rapport)); - - free(rapport); - free(t); - return 0; -} +/* + * R5.A.04 - Qualité Algorithmique + * TD Complexité algorithmique : analyse des transactions d'une banque + * + * Le programme génère des transactions pseudo-aléatoires (toujours les + * mêmes, grâce à une graine fixe), puis calcule plusieurs indicateurs + * et produit un rapport dans rapport.txt. + * + * L'empreinte affichée à la fin doit rester IDENTIQUE après vos + * optimisations : elle prouve que le résultat n'a pas changé. + * + * Interdit : modifier les constantes, la génération des données, + * le format du rapport, ou écrire les résultats « en dur ». + * + * Compilation : gcc -O2 banque.c -o banque + * Profiling : gcc -O0 -g -pg banque.c -o banque && ./banque && gprof ./banque gmon.out + */ + +#include +#include + +#define NB_TRANSACTIONS 30000 +#define NB_CLIENTS 2000 +#define NB_JOURS 1000 +#define NB_REQUETES 30000 +#define MONTANT_MONNAIE 400 +#define GRAINE 20261020UL + +typedef struct { + int id; + int client; + int jour; + long montant; /* en centimes, négatif pour un débit */ +} Transaction; + +/* ------------------------------------------------------------------ */ +/* Données (ne pas modifier) */ +/* ------------------------------------------------------------------ */ + +static unsigned long etat_alea = GRAINE; + +unsigned long alea(void) +{ + etat_alea = etat_alea * 6364136223846793005UL + 1442695040888963407UL; + return etat_alea >> 33; +} + +Transaction *generer_transactions(int n) +{ + Transaction *t = malloc(n * sizeof(Transaction)); + for (int i = 0; i < n; i++) { + t[i].id = i; + t[i].client = alea() % NB_CLIENTS; + t[i].jour = alea() % NB_JOURS; + if (i > 0 && alea() % 20 == 0) + t[i].montant = -t[alea() % i].montant; /* opération inverse */ + else + t[i].montant = (long)(alea() % 100001) - 50000; + } + for (int i = n - 1; i > 0; i--) { /* mélange des id */ + int j = alea() % (i + 1); + int tmp = t[i].id; + t[i].id = t[j].id; + t[j].id = tmp; + } + return t; +} + +/* ------------------------------------------------------------------ */ +/* Fonctions à analyser et à optimiser */ +/* ------------------------------------------------------------------ */ + +/* F1 : trie les transactions par montant croissant, puis par id */ +void trier_par_montant(Transaction *t, int n) +{ + for (int i = 1; i < n; i++) { + Transaction cle = t[i]; + int j = i - 1; + while (j >= 0 && (t[j].montant > cle.montant || + (t[j].montant == cle.montant && t[j].id > cle.id))) { + t[j + 1] = t[j]; + j--; + } + t[j + 1] = cle; + } +} + +/* F2 : nombre de clients ayant au moins une transaction */ +int nb_clients_distincts(const Transaction *t, int n) +{ + int nb = 0; + for (int i = 0; i < n; i++) { + int deja_vu = 0; + for (int j = 0; j < i; j++) { + if (t[j].client == t[i].client) { + deja_vu = 1; + break; + } + } + if (!deja_vu) + nb++; + } + return nb; +} + +/* F3 : solde total de chaque client en O(n + c) */ +void total_par_client(const Transaction *t, int n, long *totaux) +{ + for (int c = 0; c < NB_CLIENTS; c++) { + totaux[c] = 0; + } + for (int i = 0; i < n; i++) { + totaux[t[i].client] += t[i].montant; + } +} + +/* F4 : solde total de chaque jour */ +void total_par_jour(const Transaction *t, int n, long *totaux) +{ + for (int j = 0; j < NB_JOURS; j++) { + totaux[j] = 0; + for (int i = 0; i < n; i++) + if (t[i].jour == j) + totaux[j] += t[i].montant; + } +} + +/* F5 : période de jours consécutifs dont la somme des soldes est maximale */ +long meilleure_periode(const long *totaux, int nb_jours, int *debut, int *fin) +{ + long meilleur = totaux[0]; + *debut = 0; + *fin = 0; + for (int i = 0; i < nb_jours; i++) { + for (int j = i; j < nb_jours; j++) { + long somme = 0; + for (int k = i; k <= j; k++) + somme += totaux[k]; + if (somme > meilleur) { + meilleur = somme; + *debut = i; + *fin = j; + } + } + } + return meilleur; +} + +/* F6 : retrouve une transaction à partir de son id */ +const Transaction *rechercher_par_id(const Transaction *t, int n, int id) +{ + for (int i = 0; i < n; i++) + if (t[i].id == id) + return &t[i]; + return NULL; +} + +/* F7 : nombre de paires de transactions de montants opposés (a + b = 0) */ +long nb_paires_opposees(const Transaction *t, int n) +{ + long nb = 0; + for (int i = 0; i < n; i++) + for (int j = i + 1; j < n; j++) + if (t[i].montant + t[j].montant == 0) + nb++; + return nb; +} + +/* F8 : nombre de façons de rendre une somme avec les pièces disponibles */ +static const int PIECES[] = {1, 2, 5, 10, 20, 50, 100, 200}; +#define NB_PIECES 8 + +long nb_facons_rendre(int somme, int nb_pieces) +{ + if (somme == 0) + return 1; + if (somme < 0 || nb_pieces == 0) + return 0; + return nb_facons_rendre(somme - PIECES[nb_pieces - 1], nb_pieces) + + nb_facons_rendre(somme, nb_pieces - 1); +} + +/* F9 : catégorie d'une transaction (pour les statistiques) */ +int categorie(const Transaction *t) +{ + if (t->montant < 0) { + if (t->montant < -20000) { + if (t->jour % 7 == 5 || t->jour % 7 == 6) + return 1; + else + return 2; + } else if (t->montant < -5000) { + return 3; + } else { + if (t->client % 10 == 0) + return 4; + return 5; + } + } else if (t->montant == 0) { + return 0; + } else { + if (t->montant > 30000) { + if (t->client % 10 == 0 && t->jour % 7 < 5) + return 6; + return 7; + } else if (t->montant > 10000) { + return 8; + } else if (t->montant > 1000) { + if (t->jour % 30 == 0) + return 9; + return 10; + } + return 11; + } +} + +/* F10 : ajoute une ligne à la fin du rapport */ +int longueur(const char *s) +{ + int n = 0; + while (s[n] != '\0') + n++; + return n; +} + +void ajouter_ligne(char *rapport, const char *ligne) +{ + int fin = longueur(rapport); + int i = 0; + while (ligne[i] != '\0') { + rapport[fin + i] = ligne[i]; + i++; + } + rapport[fin + i] = '\0'; +} + +/* ------------------------------------------------------------------ */ +/* Programme principal (à adapter si vous changez les signatures) */ +/* ------------------------------------------------------------------ */ + +unsigned long empreinte(const char *s) +{ + unsigned long h = 1469598103934665603UL; + for (int i = 0; s[i] != '\0'; i++) { + h ^= (unsigned char)s[i]; + h *= 1099511628211UL; + } + return h; +} + +int main(void) +{ + Transaction *t = generer_transactions(NB_TRANSACTIONS); + char *rapport = malloc(1 << 20); + char ligne[128]; + rapport[0] = '\0'; + + /* recherches par id, dans l'ordre d'origine */ + long somme_requetes = 0; + unsigned long etat = 12345; + for (int q = 0; q < NB_REQUETES; q++) { + etat = etat * 1103515245UL + 12345UL; + const Transaction *r = rechercher_par_id(t, NB_TRANSACTIONS, (int)((etat >> 8) % NB_TRANSACTIONS)); + if (r != NULL) + somme_requetes += r->montant; + } + + int nb_clients = nb_clients_distincts(t, NB_TRANSACTIONS); + + static long totaux_clients[NB_CLIENTS]; + total_par_client(t, NB_TRANSACTIONS, totaux_clients); + + static long totaux_jours[NB_JOURS]; + total_par_jour(t, NB_TRANSACTIONS, totaux_jours); + int debut, fin; + long meilleure = meilleure_periode(totaux_jours, NB_JOURS, &debut, &fin); + + long nb_paires = nb_paires_opposees(t, NB_TRANSACTIONS); + + int categories[12] = {0}; + for (int i = 0; i < NB_TRANSACTIONS; i++) + categories[categorie(&t[i])]++; + + trier_par_montant(t, NB_TRANSACTIONS); + + long nb_facons = nb_facons_rendre(MONTANT_MONNAIE, NB_PIECES); + + /* rapport */ + snprintf(ligne, sizeof(ligne), "clients distincts;%d\n", nb_clients); + ajouter_ligne(rapport, ligne); + snprintf(ligne, sizeof(ligne), "somme des requetes;%ld\n", somme_requetes); + ajouter_ligne(rapport, ligne); + snprintf(ligne, sizeof(ligne), "meilleure periode;%d;%d;%ld\n", debut, fin, meilleure); + ajouter_ligne(rapport, ligne); + snprintf(ligne, sizeof(ligne), "paires opposees;%ld\n", nb_paires); + ajouter_ligne(rapport, ligne); + snprintf(ligne, sizeof(ligne), "facons de rendre %d;%ld\n", MONTANT_MONNAIE, nb_facons); + ajouter_ligne(rapport, ligne); + for (int c = 0; c < 12; c++) { + snprintf(ligne, sizeof(ligne), "categorie;%d;%d\n", c, categories[c]); + ajouter_ligne(rapport, ligne); + } + for (int c = 0; c < NB_CLIENTS; c++) { + snprintf(ligne, sizeof(ligne), "client;%d;%ld\n", c, totaux_clients[c]); + ajouter_ligne(rapport, ligne); + } + for (int j = 0; j < NB_JOURS; j++) { + snprintf(ligne, sizeof(ligne), "jour;%d;%ld\n", j, totaux_jours[j]); + ajouter_ligne(rapport, ligne); + } + for (int i = 0; i < NB_TRANSACTIONS; i += 10) { + snprintf(ligne, sizeof(ligne), "rang;%d;%d;%ld\n", i, t[i].id, t[i].montant); + ajouter_ligne(rapport, ligne); + } + + FILE *f = fopen("rapport.txt", "w"); + if (f != NULL) { + fputs(rapport, f); + fclose(f); + } + + printf("Clients distincts : %d\n", nb_clients); + printf("Somme des requêtes : %ld\n", somme_requetes); + printf("Meilleure période : jours %d à %d (%ld)\n", debut, fin, meilleure); + printf("Paires opposées : %ld\n", nb_paires); + printf("Façons de rendre %d : %ld\n", MONTANT_MONNAIE, nb_facons); + printf("Empreinte : %016lx\n", empreinte(rapport)); + + free(rapport); + free(t); + return 0; +} -- 2.54.0 From bf16afd7279c2d8e5516fe4eb4efd6e8c675c4ae Mon Sep 17 00:00:00 2001 From: Karl_FRAM Date: Wed, 21 Oct 2026 11:30:59 +0200 Subject: [PATCH 2/2] EXO 4 - optimisation F3 --- banque | Bin 21160 -> 21160 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/banque b/banque index 0ae2b468574f5d6d707dd61f119e9b6a5fcfc01f..c38444be23ae4dfa5dfba4c270ce8692673394c3 100755 GIT binary patch literal 21160 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