Réduire la complexité de F9 en séparant débits et crédits

This commit is contained in:
rabot
2026-10-21 11:16:34 +02:00
parent 5cdf32fdae
commit 3f98548446
3 changed files with 101 additions and 28 deletions
+16
View File
@@ -348,3 +348,19 @@ disparaissent. F8 passe de **M = 4 à M = 5** : l'amélioration temporelle
n'implique pas une baisse de M. Les tests comparent les résultats à la
récursion initiale pour les sommes de -2 à 40 et de 0 à 8 types de pièces,
y compris la somme nulle et l'absence de pièces.
### F9 — Séparer les règles des débits et des crédits
`categorie` répartit les transactions entre débit, montant nul et crédit.
Les règles propres aux débits et aux crédits sont regroupées dans deux
fonctions auxiliaires, avec des retours directs. Le test du week-end
`jour % 7 >= 5` remplace les deux comparaisons reliées par `||`.
Le temps reste **`O(1)`** et la complexité cyclomatique de F9 passe de
**14 à 3**, sous l'objectif de 10. Les auxiliaires `categorie_debit`
et `categorie_credit` ont respectivement **M = 5** et **M = 7** : les
décisions ne sont pas simplement déplacées vers une autre fonction
dépassant l'objectif. Les tests confrontent les 20 montants situés aux
seuils et à leurs voisins, y compris `LONG_MIN` et `LONG_MAX`, à la fonction
initiale, pour 20 clients et 210 jours (cycle commun des modulos 7 et 30),
soit **84 000 classifications**.
+35 -28
View File
@@ -259,37 +259,44 @@ long nb_facons_rendre(int somme, int nb_pieces)
}
/* F9 : catégorie d'une transaction (pour les statistiques) */
static int categorie_debit(const Transaction *t)
{
if (t->montant < -20000) {
if (t->jour % 7 >= 5)
return 1;
return 2;
}
if (t->montant < -5000)
return 3;
if (t->client % 10 == 0)
return 4;
return 5;
}
static int categorie_credit(const Transaction *t)
{
if (t->montant > 30000) {
if (t->client % 10 == 0 && t->jour % 7 < 5)
return 6;
return 7;
}
if (t->montant > 10000)
return 8;
if (t->montant > 1000) {
if (t->jour % 30 == 0)
return 9;
return 10;
}
return 11;
}
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) {
if (t->montant < 0)
return categorie_debit(t);
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;
}
return categorie_credit(t);
}
/* F10 : ajoute une ligne à la fin du rapport */
+50
View File
@@ -224,6 +224,55 @@ static void tester_monnaie(void)
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));
}
}
}
}
int main(void)
{
tester_tri();
@@ -234,6 +283,7 @@ int main(void)
tester_recherches();
tester_paires();
tester_monnaie();
tester_categories();
puts("Tests banque : OK");
return 0;
}