forked from menault/2026_TD3_DEV51_Qualite_Algo
320 lines
9.3 KiB
C
320 lines
9.3 KiB
C
/* Cas limites et comparaisons avec des algorithmes de référence simples. */
|
|
#define main banque_main
|
|
#include "../banque.c"
|
|
#undef main
|
|
|
|
#include <assert.h>
|
|
#include <limits.h>
|
|
|
|
static int comparer_reference(const void *a, const void *b)
|
|
{
|
|
const Transaction *ta = a;
|
|
const Transaction *tb = b;
|
|
if (ta->montant < tb->montant)
|
|
return -1;
|
|
if (ta->montant > tb->montant)
|
|
return 1;
|
|
if (ta->id < tb->id)
|
|
return -1;
|
|
return ta->id > tb->id;
|
|
}
|
|
|
|
static void verifier_tri(Transaction *t, int n)
|
|
{
|
|
Transaction attendu[128];
|
|
assert(n <= 128);
|
|
memcpy(attendu, t, (size_t)n * sizeof(*t));
|
|
qsort(attendu, (size_t)n, sizeof(*attendu), comparer_reference);
|
|
trier_par_montant(t, n);
|
|
for (int i = 0; i < n; i++) {
|
|
assert(t[i].id == attendu[i].id);
|
|
assert(t[i].client == attendu[i].client);
|
|
assert(t[i].jour == attendu[i].jour);
|
|
assert(t[i].montant == attendu[i].montant);
|
|
}
|
|
}
|
|
|
|
static void tester_tri(void)
|
|
{
|
|
trier_par_montant(NULL, 0);
|
|
Transaction limites[] = {
|
|
{INT_MAX, 1, 2, LONG_MAX}, {3, 4, 5, 0},
|
|
{INT_MIN, 6, 7, LONG_MIN}, {1, 8, 9, 0}, {2, 10, 11, LONG_MAX}
|
|
};
|
|
verifier_tri(limites, 5);
|
|
verifier_tri(limites, 5); /* déjà trié */
|
|
Transaction t[128];
|
|
for (int n = 1; n <= 128; n++) {
|
|
for (int i = 0; i < n; i++)
|
|
t[i] = (Transaction){n - i, i, i + 1, (i * 37) % 11 - 5};
|
|
verifier_tri(t, n);
|
|
for (int i = 0; i < n; i++)
|
|
t[i] = (Transaction){i, i, i + 1, n - i};
|
|
verifier_tri(t, n); /* ordre inverse */
|
|
}
|
|
}
|
|
|
|
static void tester_clients_distincts(void)
|
|
{
|
|
assert(nb_clients_distincts(NULL, 0) == 0);
|
|
Transaction t[NB_CLIENTS];
|
|
for (int i = 0; i < NB_CLIENTS; i++)
|
|
t[i] = (Transaction){i, NB_CLIENTS - 1, 0, 0};
|
|
assert(nb_clients_distincts(t, NB_CLIENTS) == 1);
|
|
t[0].client = 0;
|
|
assert(nb_clients_distincts(t, NB_CLIENTS) == 2);
|
|
for (int i = 0; i < NB_CLIENTS; i++)
|
|
t[i].client = i;
|
|
assert(nb_clients_distincts(t, NB_CLIENTS) == NB_CLIENTS);
|
|
assert(nb_clients_distincts(t, 1) == 1);
|
|
}
|
|
|
|
static void tester_totaux_clients(void)
|
|
{
|
|
Transaction t[] = {
|
|
{0, 0, 0, 100}, {1, NB_CLIENTS - 1, 1, -50},
|
|
{2, 0, 2, -40}, {3, NB_CLIENTS - 1, 3, 50}, {4, 7, 4, 0}
|
|
};
|
|
long totaux[NB_CLIENTS];
|
|
for (int i = 0; i < NB_CLIENTS; i++)
|
|
totaux[i] = 123;
|
|
total_par_client(t, 5, totaux);
|
|
for (int c = 0; c < NB_CLIENTS; c++) {
|
|
long attendu = 0;
|
|
for (int i = 0; i < 5; i++)
|
|
if (t[i].client == c)
|
|
attendu += t[i].montant;
|
|
assert(totaux[c] == attendu);
|
|
}
|
|
total_par_client(NULL, 0, totaux);
|
|
for (int c = 0; c < NB_CLIENTS; c++)
|
|
assert(totaux[c] == 0);
|
|
}
|
|
|
|
static void tester_totaux_jours(void)
|
|
{
|
|
Transaction t[] = {
|
|
{0, 0, NB_JOURS - 1, 100}, {1, 1, 0, -50},
|
|
{2, 2, NB_JOURS - 1, -40}, {3, 3, 0, 50}, {4, 4, 7, 0}
|
|
};
|
|
long totaux[NB_JOURS];
|
|
for (int i = 0; i < NB_JOURS; i++)
|
|
totaux[i] = 123;
|
|
total_par_jour(t, 5, totaux);
|
|
for (int j = 0; j < NB_JOURS; j++) {
|
|
long attendu = 0;
|
|
for (int i = 0; i < 5; i++)
|
|
if (t[i].jour == j)
|
|
attendu += t[i].montant;
|
|
assert(totaux[j] == attendu);
|
|
}
|
|
total_par_jour(NULL, 0, totaux);
|
|
for (int j = 0; j < NB_JOURS; j++)
|
|
assert(totaux[j] == 0);
|
|
}
|
|
|
|
static long periode_reference(const long *t, int n, int *debut, int *fin)
|
|
{
|
|
long meilleur = t[0];
|
|
*debut = 0;
|
|
*fin = 0;
|
|
for (int i = 0; i < n; i++) {
|
|
for (int j = i; j < n; j++) {
|
|
long somme = 0;
|
|
for (int k = i; k <= j; k++)
|
|
somme += t[k];
|
|
if (somme > meilleur) {
|
|
meilleur = somme;
|
|
*debut = i;
|
|
*fin = j;
|
|
}
|
|
}
|
|
}
|
|
return meilleur;
|
|
}
|
|
|
|
static void tester_periodes(void)
|
|
{
|
|
long t[7];
|
|
int nb_cas = 1;
|
|
for (int n = 1; n <= 7; n++) {
|
|
nb_cas *= 5;
|
|
for (int cas = 0; cas < nb_cas; cas++) {
|
|
int valeurs = cas;
|
|
for (int i = 0; i < n; i++) {
|
|
t[i] = valeurs % 5 - 2;
|
|
valeurs /= 5;
|
|
}
|
|
int debut, fin, debut_attendu, fin_attendue;
|
|
long attendu = periode_reference(t, n, &debut_attendu, &fin_attendue);
|
|
assert(meilleure_periode(t, n, &debut, &fin) == attendu);
|
|
assert(debut == debut_attendu);
|
|
assert(fin == fin_attendue);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void tester_recherches(void)
|
|
{
|
|
assert(rechercher_par_id(NULL, 0, 0) == NULL);
|
|
assert(rechercher_par_id(NULL, 0, -1) == NULL);
|
|
Transaction t[128];
|
|
const Transaction *index_ids[128];
|
|
for (int n = 1; n <= 128; n++) {
|
|
for (int i = 0; i < n; i++)
|
|
t[i] = (Transaction){n - 1 - i, i, i, i * 77 - 12};
|
|
indexer_par_id(t, n, index_ids);
|
|
for (int id = 0; id < n; id++) {
|
|
const Transaction *attendu = NULL;
|
|
for (int i = 0; i < n; i++)
|
|
if (t[i].id == id)
|
|
attendu = &t[i];
|
|
assert(rechercher_par_id(index_ids, n, id) == attendu);
|
|
}
|
|
assert(rechercher_par_id(index_ids, n, -1) == NULL);
|
|
assert(rechercher_par_id(index_ids, n, n) == NULL);
|
|
assert(rechercher_par_id(index_ids, n, INT_MAX) == NULL);
|
|
}
|
|
}
|
|
|
|
static long paires_reference(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;
|
|
}
|
|
|
|
static void tester_paires(void)
|
|
{
|
|
assert(nb_paires_opposees(NULL, 0) == 0);
|
|
Transaction t[7], original[7];
|
|
int nb_cas = 1;
|
|
for (int n = 1; n <= 7; n++) {
|
|
nb_cas *= 5;
|
|
for (int cas = 0; cas < nb_cas; cas++) {
|
|
int valeurs = cas;
|
|
for (int i = 0; i < n; i++) {
|
|
t[i] = (Transaction){i, i, i, valeurs % 5 - 2};
|
|
valeurs /= 5;
|
|
}
|
|
memcpy(original, t, (size_t)n * sizeof(*t));
|
|
assert(nb_paires_opposees(t, n) == paires_reference(t, n));
|
|
assert(memcmp(original, t, (size_t)n * sizeof(*t)) == 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
static long monnaie_reference(int somme, int nb_pieces)
|
|
{
|
|
if (somme == 0)
|
|
return 1;
|
|
if (somme < 0 || nb_pieces == 0)
|
|
return 0;
|
|
return monnaie_reference(somme - PIECES[nb_pieces - 1], nb_pieces) +
|
|
monnaie_reference(somme, nb_pieces - 1);
|
|
}
|
|
|
|
static void tester_monnaie(void)
|
|
{
|
|
for (int s = -2; s <= 40; s++)
|
|
for (int k = 0; k <= NB_PIECES; k++)
|
|
assert(nb_facons_rendre(s, k) == monnaie_reference(s, k));
|
|
}
|
|
|
|
static int categorie_reference(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;
|
|
}
|
|
}
|
|
|
|
static void tester_categories(void)
|
|
{
|
|
const long montants[] = {
|
|
LONG_MIN, -20001, -20000, -19999, -5001, -5000, -4999, -1,
|
|
0, 1, 999, 1000, 1001, 9999, 10000, 10001, 29999, 30000, 30001, LONG_MAX
|
|
};
|
|
for (size_t m = 0; m < sizeof(montants) / sizeof(*montants); m++) {
|
|
for (int c = 0; c < 20; c++) {
|
|
for (int j = 0; j < 210; j++) {
|
|
Transaction t = {0, c, j, montants[m]};
|
|
assert(categorie(&t) == categorie_reference(&t));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static void tester_rapport(void)
|
|
{
|
|
char rapport[4097] = "";
|
|
char attendu[4097] = "";
|
|
char *fin = rapport;
|
|
size_t taille = 0;
|
|
assert(ajouter_ligne(fin, "") == fin);
|
|
for (int i = 0; i < 200; i++) {
|
|
char ligne[20];
|
|
int longueur_ligne = snprintf(ligne, sizeof(ligne), "ligne;%d\n", i);
|
|
assert(longueur_ligne > 0);
|
|
assert((size_t)longueur_ligne < sizeof(ligne));
|
|
memcpy(attendu + taille, ligne, (size_t)longueur_ligne + 1);
|
|
taille += (size_t)longueur_ligne;
|
|
fin = ajouter_ligne(fin, ligne);
|
|
assert(fin == rapport + taille);
|
|
assert(*fin == '\0');
|
|
assert(strcmp(rapport, attendu) == 0);
|
|
assert(ajouter_ligne(fin, "") == fin);
|
|
}
|
|
char longue_ligne[4097];
|
|
memset(longue_ligne, 'x', sizeof(longue_ligne) - 1);
|
|
longue_ligne[sizeof(longue_ligne) - 1] = '\0';
|
|
rapport[0] = '\0';
|
|
fin = ajouter_ligne(rapport, longue_ligne);
|
|
assert(fin == rapport + sizeof(rapport) - 1);
|
|
assert(strcmp(rapport, longue_ligne) == 0);
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
tester_tri();
|
|
tester_clients_distincts();
|
|
tester_totaux_clients();
|
|
tester_totaux_jours();
|
|
tester_periodes();
|
|
tester_recherches();
|
|
tester_paires();
|
|
tester_monnaie();
|
|
tester_categories();
|
|
tester_rapport();
|
|
puts("Tests banque : OK");
|
|
return 0;
|
|
}
|