Ch. 00 · Leçon 3
Mini-projet 2 — Classement d'élèves au bac
Ce que vous saurez faire
- Calculer une mention à partir d'une moyenne
- Trier des élèves par moyenne décroissante
- Produire des statistiques sur une classe (admis, échec, moyenne globale)
- Combiner conditions, tableaux, tri et fonctions
25 élèves, 1 classement, 4 chapitres mobilisés
Ce mini-projet rejoue un classique du bac : produire un bulletin de classe complet à partir d'une liste de moyennes.
Énoncé
Un professeur saisit les noms et moyennes de 25 élèves de sa classe. Le programme doit :
-
Calculer la mention de chaque élève selon :
- Très Bien : moyenne ≥ 16
- Bien : 14 ≤ moyenne < 16
- Assez Bien : 12 ≤ moyenne < 14
- Passable : 10 ≤ moyenne < 12
- Refusé : moyenne < 10
-
Afficher la liste classée par moyenne décroissante (avec nom, moyenne, mention).
-
Calculer et afficher les statistiques :
- Moyenne globale de la classe.
- Nombre d'admis (moyenne ≥ 10) et taux de réussite (%).
- Nombre d'élèves par mention.
- Meilleur et pire élève (nom + moyenne).
Travail demandé
- Arbre d'analyse modulaire (au moins 5 modules).
- T.D.O complet.
- Algorithme détaillé.
- Traduction Python 3.
- Justification des structures de boucle et de l'algorithme de tri.
Pistes
💡 Indice 1 — Structure de stockage
Deux tableaux parallèles noms[25] et moyennes[25]. La cohérence d'indice doit être préservée à tout moment.
💡 Indice 2 — Fonction determiner_mention
Cascade de Si…Sinon Si… du plus restrictif (≥ 16) au plus large (< 10). Le piège classique : tester ≥ 10 en premier classe tout le monde « Passable ».
💡 Indice 3 — Tri parallèle
Choisir tri par sélection ou par bulles, peu importe pour 25 éléments. Échange des deux tableaux à chaque permutation, sinon l'association nom/moyenne est perdue.
Corrigé
📘 Voir le corrigé
Arbre d'analyse
ProgrammeClassement
│
┌────────┬──────┬──────┴──────┬───────────────┬──────────────┐
▼ ▼ ▼ ▼ ▼ ▼
saisir_ trier_ determiner_ afficher_ stats_ afficher_
classe moyennes_ mention classement admis_par_ extremes
decroissant mention
Code Python complet
def determiner_mention(m: float) -> str:
"""Retourne la mention selon la moyenne."""
if m >= 16:
return "Très Bien"
elif m >= 14:
return "Bien"
elif m >= 12:
return "Assez Bien"
elif m >= 10:
return "Passable"
else:
return "Refusé"
def saisir_classe(N: int) -> tuple[list[str], list[float]]:
noms = [""] * N
moyennes = [0.0] * N
for i in range(N):
noms[i] = input(f"Nom élève {i + 1} : ").strip()
# Validation moyenne ∈ [0, 20]
while True:
try:
m = float(input(f"Moyenne de {noms[i]} : "))
if 0 <= m <= 20:
moyennes[i] = m
break
except ValueError:
pass
print("Moyenne invalide, doit être ∈ [0, 20].")
return noms, moyennes
def trier_moyennes_decroissant(noms: list[str], moyennes: list[float]) -> None:
"""Tri par sélection décroissant des deux tableaux en parallèle."""
N = len(noms)
for i in range(N - 1):
idx_max = i
for j in range(i + 1, N):
if moyennes[j] > moyennes[idx_max]:
idx_max = j
noms[i], noms[idx_max] = noms[idx_max], noms[i]
moyennes[i], moyennes[idx_max] = moyennes[idx_max], moyennes[i]
def afficher_classement(noms: list[str], moyennes: list[float]) -> None:
print("\n--- Classement ---")
print(f"{'Rang':>4} | {'Nom':<25} | {'Moy.':>6} | Mention")
print("-" * 60)
for i in range(len(noms)):
mention = determiner_mention(moyennes[i])
print(f"{i + 1:>4} | {noms[i]:<25} | {moyennes[i]:>6.2f} | {mention}")
def moyenne_globale(moyennes: list[float]) -> float:
if not moyennes:
return 0.0
return sum(moyennes) / len(moyennes)
def stats_admission(moyennes: list[float]) -> tuple[int, float]:
nb_admis = sum(1 for m in moyennes if m >= 10)
taux = (nb_admis / len(moyennes)) * 100 if moyennes else 0.0
return nb_admis, taux
def stats_par_mention(moyennes: list[float]) -> dict[str, int]:
compteurs = {
"Très Bien": 0, "Bien": 0, "Assez Bien": 0,
"Passable": 0, "Refusé": 0,
}
for m in moyennes:
compteurs[determiner_mention(m)] += 1
return compteurs
def extremes(noms: list[str], moyennes: list[float]) -> tuple[str, float, str, float]:
"""Retourne (meilleur_nom, meilleure_moy, pire_nom, pire_moy)."""
idx_max = 0
idx_min = 0
for i in range(1, len(moyennes)):
if moyennes[i] > moyennes[idx_max]:
idx_max = i
if moyennes[i] < moyennes[idx_min]:
idx_min = i
return noms[idx_max], moyennes[idx_max], noms[idx_min], moyennes[idx_min]
# === Programme principal ===
N = 25
noms, moyennes = saisir_classe(N)
trier_moyennes_decroissant(noms, moyennes)
afficher_classement(noms, moyennes)
print("\n--- Statistiques ---")
print(f"Moyenne globale : {moyenne_globale(moyennes):.2f} / 20")
nb, taux = stats_admission(moyennes)
print(f"Admis : {nb} / {N} ({taux:.1f}%)")
print("Par mention :")
for mention, n in stats_par_mention(moyennes).items():
print(f" {mention:<12} : {n}")
best_nom, best_moy, worst_nom, worst_moy = extremes(noms, moyennes)
print(f"\nMeilleur : {best_nom} ({best_moy})")
print(f"Pire : {worst_nom} ({worst_moy})")
Justifications
- Tableaux parallèles : pas de structure composée au programme. Garder l'index aligné.
- Tri par sélection décroissant : modifier la comparaison
>au lieu de<. O(n²) acceptable pour 25 éléments. determiner_mentionséparée : réutilisable parstats_par_mention. Principe DRY (Don't Repeat Yourself).- Boucle de validation
while Truepour la saisie de moyenne (correspond àRépéter…Jusqu'àalgorithmique).
Auto-évaluation
- Arbre d'analyse avec au moins 5 modules
- T.D.O complet
-
determiner_mentioncorrecte (ordre des conditions !) - Tri par sélection décroissant sur les deux tableaux
- Statistiques (admis, mentions, extrêmes)
- Validation de saisie pour les moyennes