forked from menault/2026_TD3_DEV51_Qualite_Algo
Optimiser F5 avec Kadane en conservant les égalités
This commit is contained in:
@@ -282,3 +282,20 @@ puis ajout de chaque montant dans `totaux[t[i].jour]`. Le coût passe de
|
|||||||
La complexité cyclomatique passe de **4 à 3**. Les tests comparent chaque
|
La complexité cyclomatique passe de **4 à 3**. Les tests comparent chaque
|
||||||
solde à un calcul de référence, y compris aux bornes du tableau, puis
|
solde à un calcul de référence, y compris aux bornes du tableau, puis
|
||||||
vérifient qu'un appel sans transaction remet tous les soldes à zéro.
|
vérifient qu'un appel sans transaction remet tous les soldes à zéro.
|
||||||
|
|
||||||
|
### F5 — Meilleure période en un passage (Kadane)
|
||||||
|
|
||||||
|
La somme de la meilleure période se terminant au jour courant est conservée.
|
||||||
|
Si cette somme est négative, le prochain jour démarre une nouvelle période ;
|
||||||
|
sinon, elle est prolongée. Le coût passe de `O(J³)` à **`O(J)`**, avec
|
||||||
|
**`O(1)`** de mémoire auxiliaire, et la complexité cyclomatique de **5 à 4**.
|
||||||
|
|
||||||
|
La somme initiale est celle du premier jour : une série entièrement négative
|
||||||
|
renvoie bien un intervalle non vide. On redémarre uniquement pour une somme
|
||||||
|
strictement négative et on remplace le meilleur résultat uniquement pour
|
||||||
|
une somme strictement supérieure. Une somme nulle conserve ainsi le début
|
||||||
|
le plus ancien ; à égalité, le premier début puis la première fin sont
|
||||||
|
conservés comme dans les boucles initiales. Les **97 655 séries** de longueur
|
||||||
|
1 à 7 à valeurs dans `[-2, 2]` sont comparées à la version cubique, sur la
|
||||||
|
somme et sur les deux bornes : elles couvrent notamment les zéros, les
|
||||||
|
égalités et les séries entièrement négatives.
|
||||||
|
|||||||
@@ -146,23 +146,27 @@ void total_par_jour(const Transaction *t, int n, long *totaux)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* F5 : période de jours consécutifs dont la somme des soldes est maximale */
|
/* F5 : période de jours consécutifs dont la somme des soldes est maximale */
|
||||||
|
/* Précondition : nb_jours > 0. En cas d'égalité, garder le premier intervalle. */
|
||||||
long meilleure_periode(const long *totaux, int nb_jours, int *debut, int *fin)
|
long meilleure_periode(const long *totaux, int nb_jours, int *debut, int *fin)
|
||||||
{
|
{
|
||||||
long meilleur = totaux[0];
|
long meilleur = totaux[0];
|
||||||
|
long somme = totaux[0];
|
||||||
|
int debut_courant = 0;
|
||||||
*debut = 0;
|
*debut = 0;
|
||||||
*fin = 0;
|
*fin = 0;
|
||||||
for (int i = 0; i < nb_jours; i++) {
|
for (int j = 1; j < nb_jours; j++) {
|
||||||
for (int j = i; j < nb_jours; j++) {
|
if (somme < 0) {
|
||||||
long somme = 0;
|
somme = totaux[j];
|
||||||
for (int k = i; k <= j; k++)
|
debut_courant = j;
|
||||||
somme += totaux[k];
|
} else {
|
||||||
|
somme += totaux[j];
|
||||||
|
}
|
||||||
if (somme > meilleur) {
|
if (somme > meilleur) {
|
||||||
meilleur = somme;
|
meilleur = somme;
|
||||||
*debut = i;
|
*debut = debut_courant;
|
||||||
*fin = j;
|
*fin = j;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return meilleur;
|
return meilleur;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -113,12 +113,54 @@ static void tester_totaux_jours(void)
|
|||||||
assert(totaux[j] == 0);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
tester_tri();
|
tester_tri();
|
||||||
tester_clients_distincts();
|
tester_clients_distincts();
|
||||||
tester_totaux_clients();
|
tester_totaux_clients();
|
||||||
tester_totaux_jours();
|
tester_totaux_jours();
|
||||||
|
tester_periodes();
|
||||||
puts("Tests banque : OK");
|
puts("Tests banque : OK");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user