Leçon 18 sur 19

Chapitre 18 — Projet de synthèse

 

Concevoir, implémenter, tester et documenter une application algorithmique complète

ANALYSER  →   MODÉLISER  →  CONCEVOIR   →  IMPLÉMENTER  →   TESTER  →  JUSTIFIER

 

Fiche pédagogique du chapitre

Objectifs d’apprentissage

À la fin de ce chapitre, l’étudiant devra être capable de :

• transformer un besoin exprimé en langage naturel en spécifications fonctionnelles et techniques ;

• sélectionner les structures de données et les algorithmes les plus adaptés à un contexte donné ;

• découper une application en modules cohérents, testables et faiblement couplés ;

• rédiger des pseudo-codes précis avant de commencer l’implémentation ;

• construire des jeux de tests couvrant les cas normaux, limites et erronés ;

• justifier la correction et la complexité des opérations essentielles ;

• produire une documentation technique et utilisateur claire ;

• présenter et défendre les choix algorithmiques réalisés.

Prérequis

• tableaux, listes chaînées, piles, files, deques et tables de hachage ;

• arbres, tas et files de priorité ;

• algorithmes de tri et de recherche ;

• récursivité, programmation dynamique, méthodes gloutonnes et retour sur trace ;

• représentation et parcours de graphes ;

• analyse de complexité temporelle et spatiale ;

• fonctions, procédures, structures et modularité.

Organisation indicative

Activité

Volume conseillé

Finalité

Cadrage et analyse3 à 4 hDéfinir le besoin, les acteurs, les données et les contraintes.
Conception algorithmique5 à 7 hChoisir les structures et rédiger les pseudo-codes.
Implémentation10 à 16 hDévelopper les modules et intégrer les fonctionnalités.
Tests et mesures4 à 6 hValider les résultats et mesurer les performances.
Documentation et soutenance3 à 5 hPrésenter la solution et justifier les choix.

 

Principe directeur

Le projet ne consiste pas uniquement à obtenir un programme qui fonctionne. Il doit montrer une démarche complète : analyse, choix justifiés, conception modulaire, tests reproductibles, étude de complexité et documentation.

 

Plan du chapitre

Partie

Contenu

18.1Démarche générale et cycle de réalisation.
18.2 à 18.9Présentation détaillée des huit sujets proposés.
18.10Éléments attendus et structure du dossier final.
18.11Planification, organisation d’équipe et suivi.
18.12Tests, complexité, qualité et documentation.
18.13Grille d’évaluation et soutenance.
18.14Ateliers préparatoires et corrigés indicatifs.

 

18.1 — Démarche générale d’un projet algorithmique

Un projet de synthèse mobilise plusieurs notions du cours dans une application cohérente. La réussite dépend moins de la quantité de code que de la qualité de la démarche suivie. Une solution simple, correctement structurée et soigneusement testée est préférable à une application très ambitieuse mais fragile ou mal documentée.

18.1.1 Analyse du besoin

L’analyse transforme une idée générale en objectifs observables. Elle doit préciser les utilisateurs, les opérations qu’ils pourront effectuer, les données manipulées, les règles de gestion et les contraintes techniques.

Question

Exemples de réponses attendues

À qui le système est-il destiné ?Étudiant, administrateur, bibliothécaire, agent de réservation, planificateur.
Quel problème doit-il résoudre ?Retrouver une information, ordonnancer des tâches, calculer un chemin, gérer une attente.
Quelles sont les entrées ?Commandes, fichiers, identifiants, graphes, listes de tâches ou matrices.
Quels résultats produire ?Liste triée, chemin, confirmation, statistiques, message d’erreur.
Quelles contraintes respecter ?Unicité, capacité, priorité, ordre d’arrivée, temps de réponse, mémoire.

 

18.1.2 Spécifications fonctionnelles

Une fonctionnalité doit être formulée comme une action vérifiable. Par exemple, « rechercher un étudiant par numéro » est plus précis que « gérer les étudiants ». Chaque fonctionnalité doit indiquer ses entrées, son résultat, ses préconditions et les erreurs possibles.

  ZONE DE PSEUDO-CODE — Contrat générique d’une opération

Opération NomOperation(entrée1, entrée2)
Préconditions
    entrée1 respecte le format attendu
    entrée2 appartient au domaine autorisé
Traitement
    vérifier les données
    effectuer l’opération principale
Postconditions
    la structure reste valide
Retourner résultat ou erreur explicite

 

18.1.3 Choix des structures de données

Le choix doit partir des opérations dominantes. Une table de hachage convient aux recherches exactes fréquentes, un tas à l’extraction répétée de la meilleure priorité, une file à l’ordre d’arrivée, un graphe aux relations entre entités, et un tableau trié aux recherches dichotomiques et aux parcours séquentiels.

Besoin dominant

Structure souvent adaptée

Justification

Recherche exacte par identifiantTable de hachageAccès moyen en O(1) et détection rapide des doublons.
Extraction répétée du plus prioritaireTas / file de prioritéInsertion et extraction en O(log n).
Respect de l’ordre d’arrivéeFilePremier arrivé, premier servi.
Navigation dans un réseauGraphe avec liste d’adjacenceReprésentation compacte et parcours en O(n + m).
Classement et statistiquesTableau ou liste + algorithme de triParcours simple et comparaison expérimentale.
Retour arrière ou historiquePile ou dequeAnnulation et navigation dans les deux sens.

 

18.1.4 Découpage modulaire

Chaque module doit avoir une responsabilité principale. Le module de données ne doit pas gérer l’affichage, et l’interface ne doit pas contenir directement les algorithmes complexes. Cette séparation améliore les tests, la maintenance et la réutilisation.

  ZONE DE PSEUDO-CODE — Architecture modulaire minimale

Programme Principal
    initialiser les structures
    Répéter
        choix ← Interface.AfficherMenu()
        commande ← Interface.LireCommande(choix)
        résultat ← Service.Traiter(commande)
         Interface.AfficherRésultat(résultat)
    Jusqu’à choix = QUITTER
    Persistance.Sauvegarder()

 

Couche ou module

Responsabilité

Modèles / structuresDéfinir les entités et garantir leurs invariants.
Services algorithmiquesEffectuer recherches, tris, parcours, calculs et validations.
InterfaceLire les commandes, afficher les résultats et formater les erreurs.
PersistanceCharger et sauvegarder les données si cette fonction est demandée.
TestsVérifier séparément chaque opération puis les scénarios complets.

 

18.1.5 Cycle progressif de réalisation

1. Produire une version minimale avec une structure vide, un menu et une opération simple.

2. Ajouter une fonctionnalité à la fois et la tester immédiatement.

3. Séparer les fonctions longues en opérations plus petites.

4. Introduire les contrôles d’erreurs et les cas limites.

5. Mesurer les performances sur des tailles croissantes.

6. Refactoriser sans modifier le comportement observable.

7. Finaliser la documentation et préparer la démonstration.

Règle de travail

À tout instant, la branche principale du projet doit rester exécutable. Une fonctionnalité incomplète doit être isolée plutôt que de rendre toute l’application inutilisable.

 

18.2 — Gestion d’un réseau de transport

Finalité du projet

Modéliser des arrêts et des liaisons, rechercher des itinéraires et produire des informations utiles au voyageur.

 

Contexte et objectif

L’application représente un réseau de bus, de tramway ou de navettes. Chaque arrêt constitue un sommet et chaque liaison une arête ou un arc. Le système doit permettre d’ajouter des arrêts, de déclarer des liaisons et de rechercher un itinéraire entre deux points.

Objectifs pédagogiques

• mobiliser les graphes et les listes d’adjacence ;

• utiliser BFS pour un itinéraire contenant un nombre minimal de liaisons ;

• reconstruire un chemin avec un tableau de prédécesseurs ;

• gérer les arrêts inconnus, les réseaux déconnectés et les doublons.

Fonctionnalités minimales

• ajouter, modifier et supprimer un arrêt ;

• ajouter ou retirer une liaison entre deux arrêts ;

• afficher les voisins directs d’un arrêt ;

• tester l’existence d’un chemin ;

• retourner un itinéraire minimisant le nombre de correspondances ;

• afficher les composantes du réseau ou les arrêts inaccessibles.

Structures de données recommandées

Structure

Rôle dans le projet

Dictionnaire des arrêtsAssocier un identifiant à chaque arrêt et retrouver rapidement ses données.
Liste d’adjacenceStocker les liaisons sans utiliser une matrice volumineuse.
FileRéaliser le parcours en largeur.
Tableaux distance / prédécesseurReconstruire l’itinéraire et compter les liaisons.

 

Découpage en modules

Module

Responsabilité principale

RéseauAjouter les sommets et arêtes, vérifier les invariants.
ItinérairesEffectuer BFS, reconstruire les chemins et calculer les distances.
AdministrationImporter ou modifier les données du réseau.
InterfaceSaisir le départ et l’arrivée, afficher le trajet et les erreurs.

 

Jeux d’essai essentiels

Scénario

Données

Résultat attendu

Trajet directA relié à BChemin [A, B] et distance 1.
Plusieurs possibilitésDeux routes entre A et FRoute contenant le minimum de liaisons.
Sommet isoléG sans voisinsMessage « aucun itinéraire ».
Arrêt inconnuDépart X absentErreur contrôlée sans arrêt du programme.
Départ = arrivéeA vers AChemin [A] et distance 0.

 

Analyse de complexité attendue

Opération

Complexité à justifier

Ajout d’un arrêtO(1) moyen avec dictionnaire.
Ajout d’une liaisonO(1) ou O(degré) selon la vérification des doublons.
Recherche d’itinéraire par BFSO(n + m).
Mémoire du réseauO(n + m) avec listes d’adjacence.

 

Extensions possibles

• associer un temps ou une distance aux liaisons ;

• gérer des lignes et des correspondances ;

• importer les données depuis un fichier ;

• proposer plusieurs itinéraires ;

• visualiser le réseau de manière graphique.

  ZONE DE PSEUDO-CODE — Itinéraire minimal en nombre de liaisons

Fonction ItineraireBFS(graphe, départ, arrivée)
    Si départ ou arrivée n’existe pas Alors
        Retourner ERREUR_ARRET_INCONNU
    FinSi

    Pour chaque sommet s Faire
        visité[s] ← Faux
        prédécesseur[s] ← NUL
    FinPour

    file ← FileVide()
    Enfiler(file, départ)
    visité[départ] ← Vrai

    TantQue file non vide Faire
        u ← Défiler(file)
        Si u = arrivée Alors
            Retourner ReconstruireChemin(prédécesseur, départ, arrivée)
        FinSi
        Pour chaque voisin v de u Faire
            Si NON visité[v] Alors
                visité[v] ← Vrai
                prédécesseur[v] ← u
                Enfiler(file, v)
            FinSi
        FinPour
    FinTantQue
    Retourner AUCUN_CHEMIN

   Remarque : La distance obtenue est minimale uniquement lorsque chaque liaison compte pour une unité.

 

18.3 — Moteur de recherche dans un dictionnaire

Finalité du projet

Organiser un ensemble de mots et fournir des recherches exactes, alphabétiques et par préfixe.

 

Contexte et objectif

Le système stocke des mots accompagnés d’une définition, d’une catégorie ou d’exemples. Il doit permettre la recherche exacte, la consultation alphabétique et éventuellement les suggestions par préfixe.

Objectifs pédagogiques

• combiner table de hachage et structure ordonnée ;

• comparer recherche exacte, recherche dichotomique et parcours par préfixe ;

• normaliser les chaînes pour gérer casse et espaces ;

• concevoir une interface de recherche robuste.

Fonctionnalités minimales

• ajouter un mot et empêcher les doublons ;

• modifier ou supprimer une entrée ;

• retrouver exactement un mot ;

• afficher les mots dans l’ordre alphabétique ;

• rechercher tous les mots commençant par un préfixe ;

• afficher un message clair lorsqu’aucun résultat n’est trouvé.

Structures de données recommandées

Structure

Rôle dans le projet

Table de hachageRecherche exacte moyenne en O(1).
Tableau trié ou ABRConsultation alphabétique et recherche d’intervalle.
Liste de résultatsStocker les suggestions avant affichage.
Enregistrement MotRegrouper terme, définition, catégorie et exemples.

 

Découpage en modules

Module

Responsabilité principale

DictionnaireMaintenir les entrées et l’unicité des mots.
NormalisationConvertir la casse, nettoyer les espaces et accents selon les règles.
RechercheRecherche exacte, alphabétique et par préfixe.
Import / exportLire ou écrire un fichier de mots.
InterfacePrésenter les résultats et les suggestions.

 

Jeux d’essai essentiels

Scénario

Données

Résultat attendu

Recherche exacteMot présentDéfinition correcte retournée.
Casse différente« Algorithme » / « algorithme »Même entrée selon la politique choisie.
Préfixe multiplepréfixe « pro »Tous les mots correspondants, triés.
DoublonAjout d’un mot existantRefus ou mise à jour explicite.
Mot absentclé inconnueRésultat vide sans exception non contrôlée.

 

Analyse de complexité attendue

Opération

Complexité à justifier

Recherche exacteO(1) moyen par hachage, O(n) au pire.
AjoutO(1) moyen + coût éventuel de maintien de l’ordre.
Recherche par préfixeO(n) avec parcours simple ou O(log n + k) sur tableau trié.
Affichage triéO(n log n) si un tri est effectué à la demande.

 

Extensions possibles

• ajouter un historique des recherches ;

• proposer des corrections pour une faute simple ;

• calculer les mots les plus consultés ;

• gérer plusieurs langues ;

• ajouter des synonymes et des relations entre mots.

  ZONE DE PSEUDO-CODE — Recherche de mots par préfixe dans un tableau trié

Fonction RechercherPréfixe(tableauTrié, préfixe)
    résultat ← ListeVide()
    position ← PremièrePositionPossible(tableauTrié, préfixe)

    TantQue position < Taille(tableauTrié) ET
             CommencePar(tableauTrié[position].mot, préfixe) Faire
        AjouterFin(résultat, tableauTrié[position])
        position ← position + 1
    FinTantQue
    Retourner résultat

   Remarque : La fonction PremièrePositionPossible peut être obtenue par une recherche dichotomique adaptée.

 

18.4 — Gestionnaire de tâches avec priorités

Finalité du projet

Planifier des tâches selon leur urgence tout en conservant des informations de suivi et d’historique.

 

Contexte et objectif

L’application gère des tâches caractérisées par un identifiant, une description, une priorité, une échéance et un état. L’utilisateur doit pouvoir insérer des tâches et extraire rapidement celle qui doit être traitée en premier.

Objectifs pédagogiques

• utiliser un tas comme file de priorité ;

• définir une règle de comparaison multicritère ;

• maintenir la cohérence lors des mises à jour de priorité ;

• conserver un historique des tâches terminées.

Fonctionnalités minimales

• créer une tâche avec priorité et échéance ;

• consulter la prochaine tâche à exécuter ;

• extraire et marquer la tâche prioritaire comme terminée ;

• modifier la priorité d’une tâche ;

• annuler une tâche ;

• afficher les tâches en attente et l’historique.

Structures de données recommandées

Structure

Rôle dans le projet

Tas minimum ou maximumExtraire la tâche prioritaire en O(log n).
Dictionnaire id → positionRetrouver une tâche dans le tas pour modifier sa priorité.
Pile ou listeConserver l’historique des tâches terminées.
Enregistrement TâcheStocker identifiant, priorité, échéance, état et description.

 

Découpage en modules

Module

Responsabilité principale

GestionnairePrioritésInsérer, extraire, modifier et supprimer dans le tas.
TâchesValider et gérer le cycle de vie des tâches.
HistoriqueConserver les tâches terminées ou annulées.
InterfaceAfficher une vue claire des priorités et des échéances.

 

Jeux d’essai essentiels

Scénario

Données

Résultat attendu

Priorités distinctes5 tâchesOrdre conforme aux priorités.
Priorités égalesmême priorité, dates différentesÉchéance la plus proche ou ordre d’arrivée.
Modificationpriorité 5 → 1Remontée correcte dans le tas.
Extraction videaucune tâcheMessage « aucune tâche ».
Identifiant dupliquémême idInsertion refusée.

 

Analyse de complexité attendue

Opération

Complexité à justifier

InsertionO(log n).
Consulter le sommetO(1).
Extraction prioritaireO(log n).
Modification avec dictionnaire de positionsO(log n).
Affichage trié completO(n log n) sans détruire le tas original.

 

Extensions possibles

• gérer des dépendances entre tâches sous forme de graphe ;

• détecter les tâches en retard ;

• ajouter des catégories et filtres ;

• sauvegarder automatiquement l’état ;

• simuler un ordonnanceur de processeur.

  ZONE DE PSEUDO-CODE — Extraction de la tâche prioritaire

Fonction ExtrairePrioritaire(tas)
    Si tas.taille = 0 Alors
        Retourner ERREUR_FILE_VIDE
    FinSi

    prioritaire ← tas[0]
    tas[0] ← tas[tas.taille - 1]
    tas.taille ← tas.taille - 1
    MettreÀJourPosition(tas[0], 0)
    Descendre(tas, 0)
    SupprimerPosition(prioritaire.id)
    Retourner prioritaire

 

18.5 — Système de réservation avec file d’attente

Finalité du projet

Gérer des places limitées, confirmer les réservations et promouvoir automatiquement les personnes en attente.

 

Contexte et objectif

Le système gère un événement ou une ressource de capacité limitée. Lorsque toutes les places sont occupées, les nouvelles demandes sont placées en file d’attente. Une annulation libère une place et déclenche la promotion de la première demande admissible.

Objectifs pédagogiques

• appliquer correctement le principe FIFO ;

• combiner file, dictionnaire et ensembles pour garantir l’unicité ;

• maintenir des invariants de capacité ;

• traiter les annulations et promotions de manière atomique.

Fonctionnalités minimales

• créer une ressource avec une capacité ;

• enregistrer une réservation confirmée si une place existe ;

• placer la demande en attente sinon ;

• annuler une réservation ou une demande en attente ;

• promouvoir automatiquement la première personne en attente ;

• afficher le nombre de places et la position dans la file.

Structures de données recommandées

Structure

Rôle dans le projet

FileRespecter l’ordre d’arrivée des demandes en attente.
DictionnaireRetrouver rapidement une réservation par identifiant.
EnsembleEmpêcher une personne de réserver deux fois la même ressource.
Enregistrement RéservationStocker état, date, utilisateur et ressource.

 

Découpage en modules

Module

Responsabilité principale

RessourcesGérer capacité et places disponibles.
RéservationsConfirmer, annuler et contrôler l’unicité.
AttenteEnfiler, défiler et afficher les positions.
NotificationsProduire un message lors d’une confirmation ou promotion.
InterfacePrésenter les états de réservation.

 

Jeux d’essai essentiels

Scénario

Données

Résultat attendu

Capacité disponible2 places, 1 demandeRéservation confirmée.
Capacité pleine2 places occupéesNouvelle demande en attente.
Annulationfile non videPremière demande promue.
Doublonmême utilisateur et ressourceRefus contrôlé.
Annulation inconnueid absentErreur explicite, état inchangé.

 

Analyse de complexité attendue

Opération

Complexité à justifier

Confirmation / rechercheO(1) moyen avec dictionnaire.
Ajout en attenteO(1).
PromotionO(1) pour défiler.
Suppression au milieu de la fileO(n) avec file simple ; discuter une amélioration.

 

Extensions possibles

• gérer plusieurs événements ;

• introduire une priorité pour certains profils ;

• ajouter une date limite de confirmation ;

• produire des statistiques de remplissage ;

• simuler les arrivées et annulations.

  ZONE DE PSEUDO-CODE — Annulation et promotion automatique

Procédure AnnulerRéservation(système, identifiant)
    réservation ← système.parId[identifiant]
    Si réservation n’existe pas Alors
        Signaler ERREUR_INCONNUE
        Retourner
    FinSi

    Si réservation.état = CONFIRMÉE Alors
        réservation.état ← ANNULÉE
        système.placesDisponibles ← système.placesDisponibles + 1

        Si fileAttente non vide Alors
            suivante ← Défiler(fileAttente)
            suivante.état ← CONFIRMÉE
            système.placesDisponibles ← système.placesDisponibles - 1
            Notifier(suivante)
        FinSi
    Sinon
        RetirerDeLaFile(fileAttente, réservation)
        réservation.état ← ANNULÉE
    FinSi

 

18.6 — Analyse d’un réseau social

Finalité du projet

Représenter des relations entre utilisateurs et calculer connexité, distances et groupes.

 

Contexte et objectif

Les utilisateurs sont représentés par des sommets et les relations par des arêtes. Le programme doit permettre de gérer les relations, de rechercher des chemins de connaissance et d’analyser la structure du réseau.

Objectifs pédagogiques

• modéliser un domaine réel par un graphe ;

• appliquer DFS et BFS à des questions concrètes ;

• calculer degrés, composantes et distances ;

• protéger la cohérence des relations symétriques.

Fonctionnalités minimales

• ajouter et supprimer un utilisateur ;

• ajouter ou retirer une relation ;

• afficher les contacts directs ;

• calculer le nombre minimal d’intermédiaires entre deux personnes ;

• déterminer si le réseau est connexe ;

• identifier les composantes et les utilisateurs les plus connectés.

Structures de données recommandées

Structure

Rôle dans le projet

Dictionnaire utilisateursAccès rapide aux profils par identifiant.
Graphe non orientéReprésenter des relations réciproques.
File / pileEffectuer BFS ou DFS.
Tableaux distance / parentMesurer et reconstruire les chaînes de relations.

 

Découpage en modules

Module

Responsabilité principale

ProfilsGérer les informations des utilisateurs.
RelationsGarantir symétrie, absence de doublon et suppression propre.
AnalysesDegrés, composantes, chemins et distances.
RapportsProduire classements et statistiques.
InterfaceAfficher les résultats de façon compréhensible.

 

Jeux d’essai essentiels

Scénario

Données

Résultat attendu

Relation directeA—BDistance 1.
ChaîneA—B—C—DDistance A-D = 3 et chemin correct.
Composantesdeux groupes séparésDeux composantes détectées.
Relation doublonA—B déjà existanteAucune duplication.
Suppression utilisateursommet avec voisinsToutes les arêtes associées supprimées.

 

Analyse de complexité attendue

Opération

Complexité à justifier

Ajout d’une relationO(1) moyen ou O(degré) selon la structure des voisins.
Parcours completO(n + m).
Distance minimale non pondéréeO(n + m) par BFS.
Classement des degrésO(n + m), puis O(n log n) pour trier.

 

Extensions possibles

• suggérer des contacts par amis communs ;

• calculer un coefficient de proximité simplifié ;

• gérer des relations orientées « suivre » ;

• importer un réseau volumineux ;

• visualiser les composantes.

  ZONE DE PSEUDO-CODE — Suggestions par contacts communs

Fonction SuggérerContacts(graphe, utilisateur)
    score ← DictionnaireVide()

    Pour chaque ami dans Voisins(utilisateur) Faire
        Pour chaque candidat dans Voisins(ami) Faire
            Si candidat ≠ utilisateur ET
               candidat n’est pas déjà voisin de utilisateur Alors
                score[candidat] ← score[candidat] + 1
            FinSi
        FinPour
    FinPour

    Retourner TrierParValeurDécroissante(score)

 

18.7 — Gestion d’un catalogue avec table de hachage

Finalité du projet

Créer un catalogue consultable efficacement et étudier l’influence des collisions et du facteur de charge.

 

Contexte et objectif

Le catalogue peut contenir des livres, produits, composants ou ressources pédagogiques. Chaque élément est identifié par une clé unique. Le projet doit rendre visibles les bénéfices et limites du hachage, notamment les collisions et le redimensionnement.

Objectifs pédagogiques

• implémenter une table de hachage ou instrumenter une structure existante ;

• gérer collisions, suppression et redimensionnement ;

• comparer plusieurs fonctions ou stratégies de hachage ;

• mesurer le facteur de charge et les performances.

Fonctionnalités minimales

• ajouter, rechercher, modifier et supprimer un article ;

• détecter les clés dupliquées ;

• afficher le facteur de charge ;

• redimensionner la table au-delà d’un seuil ;

• produire des statistiques sur les collisions ;

• filtrer ou trier les articles pour l’affichage.

Structures de données recommandées

Structure

Rôle dans le projet

Table de hachageIndex principal par identifiant.
Chaînes ou sondageRésoudre les collisions.
Tableau / listeAfficher, filtrer et trier les enregistrements.
Enregistrement ArticleRegrouper clé, libellé, catégorie, quantité et prix.

 

Découpage en modules

Module

Responsabilité principale

HachageCalcul de l’indice et résolution des collisions.
CatalogueRègles de gestion des articles.
StatistiquesFacteur de charge, collisions, longueurs de chaînes.
Tri / filtreProduire des vues ordonnées.
Import / exportCharger et sauvegarder les données.

 

Jeux d’essai essentiels

Scénario

Données

Résultat attendu

Clés sans collisionpetit ensembleInsertion et recherche correctes.
Collisions forcéesclés ayant le même indiceToutes restent accessibles.
Suppressionélément au milieu d’une chaîneAutres éléments préservés.
Redimensionnementseuil dépasséToutes les clés sont réinsérées.
Clé absenterecherche inconnueRésultat vide contrôlé.

 

Analyse de complexité attendue

Opération

Complexité à justifier

Recherche / insertion moyenneO(1) si la répartition est correcte.
Pire casO(n) si les collisions se concentrent.
RedimensionnementO(n) ponctuel, coût amorti à discuter.
Affichage triéO(n log n).

 

Extensions possibles

• comparer chaînage séparé et adressage ouvert ;

• tester plusieurs tailles de table ;

• ajouter un cache des recherches fréquentes ;

• gérer les seuils de stock ;

• produire un rapport expérimental sur les collisions.

  ZONE DE PSEUDO-CODE — Redimensionnement d’une table de hachage

Procédure Redimensionner(table)
    ancienne ← table.seaux
    nouvelleTaille ← ProchainNombrePremier(2 × table.taille)
    table.seaux ← CréerSeaux(nouvelleTaille)
    table.taille ← nouvelleTaille
    table.nombreÉléments ← 0

    Pour chaque seau dans ancienne Faire
        Pour chaque entrée dans seau Faire
             InsérerSansTesterSeuil(table, entrée.clé, entrée.valeur)
        FinPour
    FinPour

 

18.8 — Résolution automatique d’un labyrinthe

Finalité du projet

Transformer une grille en graphe implicite et rechercher un chemin valide ou minimal entre une entrée et une sortie.

 

Contexte et objectif

Le labyrinthe est une matrice contenant des cases libres, des obstacles, une entrée et une sortie. Chaque case libre est un sommet implicite relié à ses voisines accessibles. Le système doit rechercher un chemin et afficher sa trace.

Objectifs pédagogiques

• modéliser un graphe sans construire explicitement toutes ses arêtes ;

• comparer DFS et BFS ;

• reconstruire un chemin à partir des prédécesseurs ;

• gérer les limites de la grille et les labyrinthes sans solution.

Fonctionnalités minimales

• charger ou saisir une grille ;

• valider l’existence d’une entrée et d’une sortie ;

• rechercher un chemin quelconque avec DFS ;

• rechercher un chemin minimal avec BFS ;

• marquer et afficher les cases du chemin ;

• comparer le nombre de cases explorées.

Structures de données recommandées

Structure

Rôle dans le projet

MatriceStocker murs, cases libres, départ, sortie et chemin.
FileBFS et chemin minimal en nombre de déplacements.
Pile / récursivitéDFS et exploration avec retour sur trace.
Dictionnaire ou matrices parentReconstruction du chemin.

 

Découpage en modules

Module

Responsabilité principale

GrilleLecture, validation et génération des voisins.
SolveurDFSRecherche d’un chemin quelconque.
SolveurBFSRecherche d’un chemin minimal.
VisualisationAfficher exploration et chemin final.
MesuresComparer longueur, temps et nombre de cases visitées.

 

Jeux d’essai essentiels

Scénario

Données

Résultat attendu

Chemin directcouloir simpleChemin exact.
Plusieurs cheminsroutes de longueurs différentesBFS choisit la plus courte.
Aucune solutionsortie enferméeMessage contrôlé.
Grille minimaleentrée adjacente à la sortieLongueur 1.
Entrée invalideabsence de départErreur de validation.

 

Analyse de complexité attendue

Opération

Complexité à justifier

Exploration DFSO(L × C) au pire.
Exploration BFSO(L × C) au pire.
Mémoire BFSO(L × C).
ReconstructionO(longueur du chemin).

 

Extensions possibles

• générer aléatoirement des labyrinthes ;

• autoriser des déplacements diagonaux ;

• associer un coût à certaines cases ;

• animer l’exploration ;

• comparer avec une méthode heuristique en extension.

  ZONE DE PSEUDO-CODE — BFS sur une grille

Fonction RésoudreBFS(grille, départ, sortie)
    file ← FileVide()
    Enfiler(file, départ)
    visité[départ] ← Vrai
    parent[départ] ← NUL

    TantQue file non vide Faire
        case ← Défiler(file)
        Si case = sortie Alors
            Retourner Reconstruire(parent, départ, sortie)
        FinSi

        Pour chaque voisin accessible de case Faire
            Si NON visité[voisin] Alors
                visité[voisin] ← Vrai
                parent[voisin] ← case
                Enfiler(file, voisin)
            FinSi
        FinPour
    FinTantQue
    Retourner AUCUNE_SOLUTION

 

18.9 — Comparateur d’algorithmes de tri

Finalité du projet

Implémenter, instrumenter et comparer plusieurs méthodes de tri sur des jeux de données contrôlés.

 

Contexte et objectif

L’application exécute plusieurs algorithmes sur les mêmes données, vérifie les résultats et mesure le nombre de comparaisons, d’échanges, de déplacements, le temps et la mémoire auxiliaire.

Objectifs pédagogiques

• relier analyse théorique et mesures expérimentales ;

• concevoir une instrumentation non ambiguë ;

• générer des jeux de données reproductibles ;

• interpréter les résultats sans se limiter au temps brut.

Fonctionnalités minimales

• implémenter au moins quatre tris parmi sélection, bulles, insertion, fusion, rapide et tas ;

• copier le tableau initial avant chaque essai ;

• mesurer comparaisons et déplacements ;

• tester des données aléatoires, triées, inversées et presque triées ;

• vérifier automatiquement que le résultat est trié ;

• produire un tableau ou un fichier récapitulatif.

Structures de données recommandées

Structure

Rôle dans le projet

TableauxStocker et dupliquer les jeux de données.
Enregistrement MesureConserver taille, distribution, temps, comparaisons et déplacements.
Dictionnaire algorithmesAssocier un nom à une fonction de tri.
Liste de résultatsComparer et exporter les expériences.

 

Découpage en modules

Module

Responsabilité principale

GénérateurCréer les différentes distributions de données.
AlgorithmesContenir des implémentations indépendantes.
InstrumentationCompter et mesurer selon une convention commune.
ValidationVérifier tri, conservation des éléments et stabilité éventuelle.
RapportsProduire tableaux, classements et commentaires.

 

Jeux d’essai essentiels

Scénario

Données

Résultat attendu

Petite taillen = 0, 1, 2Aucune erreur et résultat exact.
Déjà trién croissantInsertion et bulles optimisé performants.
Inverséordre décroissantComportement défavorable visible.
Doublonsvaleurs répétéesConservation de toutes les occurrences.
Grande tailleplusieurs milliersÉcart entre O(n²) et O(n log n).

 

Analyse de complexité attendue

Opération

Complexité à justifier

Tris simplesO(n²), avec meilleurs cas spécifiques.
Tri fusionΘ(n log n), mémoire O(n).
Tri rapideO(n log n) moyen, O(n²) au pire.
Tri par tasO(n log n), mémoire O(1) en place.
Campagne expérimentaleNombre d’essais × tailles × algorithmes.

 

Extensions possibles

• produire des graphiques de performance ;

• concevoir un choix automatique de l’algorithme ;

• tester la stabilité avec des enregistrements ;

• analyser l’effet du pivot dans le tri rapide ;

• comparer une version récursive et une version itérative.

  ZONE DE PSEUDO-CODE — Campagne expérimentale reproductible

Procédure ComparerTris(algorithmes, tailles, distributions, répétitions)
    Pour chaque n dans tailles Faire
        Pour chaque distribution dans distributions Faire
            Pour essai allant de 1 à répétitions Faire
                original ← Générer(n, distribution, graine = essai)

                Pour chaque algorithme dans algorithmes Faire
                    données ← Copier(original)
                     RéinitialiserCompteurs()
                    début ← TempsCourant()
                    algorithme(données)
                    durée ← TempsCourant() - début
                     VérifierTriEtPermutation(original, données)
                    Enregistrer(n, distribution, algorithme, durée, compteurs)
                FinPour
            FinPour
        FinPour
    FinPour

   Remarque : La même graine doit produire le même tableau afin que les algorithmes soient comparés sur des données identiques.

 

18.10 — Éléments attendus dans chaque projet

18.10.1 Analyse du besoin

Le dossier doit présenter le contexte, les utilisateurs, les fonctionnalités, les entrées et sorties, les règles de gestion, les erreurs et les limites du périmètre. Une fonctionnalité non demandée mais ajoutée doit être clairement identifiée comme extension.

Élément

Questions auxquelles répondre

ContextePourquoi l’application est-elle utile ? Quel problème concret résout-elle ?
ActeursQui utilise le système et avec quels droits ?
FonctionnalitésQuelles opérations minimales et quelles extensions ?
DonnéesQuels champs, formats, contraintes d’unicité et volumes ?
ErreursComment sont traitées les saisies invalides et les états impossibles ?
Critères de réussiteComment démontrer objectivement que la fonction est correcte ?

 

18.10.2 Choix des structures de données

Chaque structure choisie doit être reliée aux opérations les plus fréquentes. Le dossier doit également mentionner au moins une alternative et expliquer pourquoi elle a été écartée.

  ZONE DE PSEUDO-CODE — Gabarit de justification

Besoin principal : ........................................
Structure retenue : ......................................
Opérations dominantes : ..................................
Complexités attendues : ..................................
Alternative étudiée : ....................................
Raison du choix final : ...................................

 

18.10.3 Découpage en modules

Le découpage doit être visible dans l’organisation du code et dans un diagramme simple. Les dépendances entre modules doivent être orientées vers des interfaces stables.

Critère

Attendu

Responsabilité uniqueUn module traite un domaine cohérent.
CohésionLes fonctions d’un même module travaillent sur les mêmes concepts.
Couplage limitéLes détails internes ne sont pas exposés inutilement.
TestabilitéLes fonctions algorithmiques peuvent être testées sans interface interactive.
NommageLes noms décrivent clairement les rôles et les données.

 

18.10.4 Pseudo-code

Les opérations importantes doivent être décrites en pseudo-code avant leur traduction. Le pseudo-code doit expliciter les entrées, sorties, conditions d’arrêt, invariants et erreurs. Il ne doit pas reproduire mot à mot la syntaxe d’un langage particulier.

Minimum conseillé

Présenter au moins quatre pseudo-codes : une opération de création ou insertion, une recherche, une modification ou suppression, et l’algorithme principal du projet.

 

18.10.5 Implémentation

• respecter une convention de nommage constante ;

• éviter les variables globales non justifiées ;

• limiter la taille des fonctions ;

• séparer les calculs de l’affichage ;

• centraliser les validations répétées ;

• documenter les interfaces publiques ;

• utiliser un système de versions et des commits compréhensibles.

18.10.6 Jeux de tests

Les tests doivent couvrir les opérations isolées et les scénarios complets. Ils doivent indiquer les données, le résultat attendu, le résultat obtenu et le statut du test.

Catégorie

Exemples

Cas normalDonnées valides, structure non vide, opération réalisable.
Cas limiteStructure vide, un seul élément, capacité exactement atteinte.
Cas erronéIdentifiant inconnu, format invalide, doublon interdit.
Cas défavorableArbre dégénéré, nombreuses collisions, données inversées.
Test de régressionScénario ayant révélé un défaut et conservé après correction.
Test de performanceTailles croissantes et mesure reproductible.

 

18.10.7 Analyse de complexité

L’analyse doit porter sur les opérations principales, dans le meilleur cas et le pire cas lorsque la distinction est utile. Les hypothèses doivent être explicites : table de hachage bien répartie, graphe représenté par listes d’adjacence, tas équilibré par définition, etc.

  ZONE DE PSEUDO-CODE — Tableau type d’analyse

Opération              Structure       Temps moyen    Pire cas    Mémoire
---------------------   --------------   -------------  ----------  --------
Ajouter                 ..............   .............  ..........  ........
Rechercher              ..............   .............  ..........  ........
Supprimer               ..............   .............  ..........  ........
Algorithme principal    ..............   .............  ..........  ........

 

18.10.8 Documentation

Document

Contenu minimal

READMEObjectif, installation, lancement, exemples et limitations.
Dossier de conceptionAnalyse, structures, modules, pseudo-codes et complexité.
Guide utilisateurCommandes, scénarios et messages d’erreur.
Rapport de testsJeux d’essai, résultats et anomalies corrigées.
Commentaires du codeContrats, décisions non évidentes et invariants.
PrésentationProblème, démonstration, choix, mesures et conclusion.

 

18.11 — Planification et organisation du travail

18.11.1 Jalons recommandés

Jalon

Livrable

Critère de validation

J1 — CadrageFiche du besoin et périmètreFonctionnalités observables et contraintes explicites.
J2 — ConceptionStructures, modules et pseudo-codesChoix justifiés et interfaces définies.
J3 — PrototypeVersion minimale exécutableScénario principal fonctionnel.
J4 — FonctionnalitésVersion complèteToutes les exigences minimales sont intégrées.
J5 — ValidationTests et mesuresCas limites couverts et résultats reproductibles.
J6 — LivraisonCode, rapport et présentationDossier cohérent et démonstration préparée.

 

18.11.2 Travail individuel ou en équipe

Le projet peut être réalisé individuellement ou par groupes de deux à quatre étudiants. Dans une équipe, les tâches doivent être distribuées sans créer des sous-projets indépendants qui ne seraient assemblés qu’à la fin.

Rôle possible

Responsabilités

Responsable du cadrageMaintenir les exigences et vérifier le périmètre.
Responsable structuresDéfinir les modèles et invariants.
Responsable algorithmesImplémenter et analyser les opérations principales.
Responsable testsConcevoir les jeux d’essai et automatiser les vérifications.
Responsable documentationUnifier le rapport, le guide et la présentation.

 

Attention

Les rôles facilitent l’organisation mais ne doivent pas empêcher la compréhension collective. Chaque membre doit pouvoir expliquer l’architecture et au moins un algorithme central.

 

18.11.3 Journal de suivi

Date

Travail réalisé

Décision / difficulté

Action suivante

 

18.12 — Validation, qualité et performance

18.12.1 Invariants à vérifier

• un identifiant unique n’apparaît pas deux fois ;

• la taille annoncée correspond au nombre réel d’éléments ;

• les indices d’un tas restent cohérents après un échange ;

• une relation non orientée est présente dans les deux listes de voisins ;

• le nombre de places confirmées ne dépasse jamais la capacité ;

• un chemin retourné relie réellement le départ à l’arrivée ;

• un tri conserve exactement les mêmes éléments que l’entrée.

18.12.2 Validation automatique

  ZONE DE PSEUDO-CODE — Structure d’un test automatisé

Procédure Tester(nom, données, attendu)
    obtenu ← ExécuterScénario(données)
    Si obtenu = attendu Alors
        Afficher("[OK] " + nom)
    Sinon
        Afficher("[ÉCHEC] " + nom)
        Afficher("Attendu : ", attendu)
        Afficher("Obtenu  : ", obtenu)
    FinSi

 

18.12.3 Mesure des performances

1. Choisir une opération et définir précisément ce qui est mesuré.

2. Générer plusieurs tailles de données et fixer les graines aléatoires.

3. Répéter chaque essai pour réduire l’influence du bruit.

4. Séparer le temps de génération des données du temps de l’algorithme.

5. Présenter les résultats sous forme de tableau ou de graphique.

6. Comparer la tendance mesurée à la complexité théorique.

7. Interpréter les écarts en tenant compte du langage et de l’implémentation.

18.12.4 Erreurs fréquentes

Erreur

Conséquence

Prévention

Coder avant de définir le besoinFonctionnalités incohérentes ou inutiles.Valider le périmètre et les scénarios.
Choisir une structure par habitudeOpérations coûteuses ou code complexe.Partir des opérations dominantes.
Mélanger interface et algorithmesTests difficiles et duplication.Créer des services indépendants.
Tester uniquement le cas nominalDéfauts lors des limites et erreurs.Construire une matrice de tests.
Mesurer une seule exécutionRésultat instable et peu interprétable.Répéter et utiliser des données identiques.
Présenter une complexité sans hypothèseConclusion ambiguë ou incorrecte.Préciser la représentation et le cas analysé.
Documentation rédigée à la finInformations manquantes et incohérences.Maintenir le README et le journal en continu.

 

18.13 — Évaluation du projet

18.13.1 Grille proposée sur 100 points

Critère

Points

Indicateurs

Analyse du besoin10Périmètre clair, fonctionnalités testables, contraintes identifiées.
Choix des structures15Choix justifiés, alternatives discutées, invariants corrects.
Conception modulaire10Responsabilités séparées et interfaces cohérentes.
Algorithmes et pseudo-codes15Correction, précision, terminaison et gestion des erreurs.
Implémentation15Code lisible, exécutable, robuste et conforme à la conception.
Tests12Cas normaux, limites, erreurs et régressions.
Complexité et mesures8Analyse exacte et expérimentation interprétée.
Documentation7README, rapport et guide complets.
Démonstration et soutenance8Présentation structurée, réponses maîtrisées et démonstration fiable.

 

18.13.2 Critères éliminatoires ou plafonnants

• projet non exécutable ou dépendances non documentées ;

• absence de contribution identifiable d’un membre ;

• pseudo-code ou code copié sans compréhension démontrée ;

• données de test absentes ou résultats falsifiés ;

• fonctionnalité centrale non implémentée ;

• rapport ne correspondant pas à la version livrée.

18.13.3 Déroulement conseillé de la soutenance

Séquence

Durée indicative

Contenu

Problème et objectifs2 minContexte, utilisateurs et périmètre.
Conception3 minStructures, modules et choix algorithmiques.
Démonstration5 à 7 minScénarios normaux et un cas limite.
Tests et complexité3 minRésultats, mesures et interprétation.
Bilan2 minLimites, difficultés et perspectives.
Questions5 minJustification des décisions et maîtrise du code.

 

18.14 — Ateliers préparatoires

Atelier 1 — Transformer un besoin en fonctionnalités

Pour le système de réservation, rédiger cinq fonctionnalités sous la forme « acteur + action + résultat observable », puis préciser une erreur possible pour chacune.

Correction indicative

Fonctionnalité

Résultat observable

Erreur possible

Réserver une placeStatut confirmé ou en attente.Utilisateur déjà inscrit.
Annuler une réservationPlace libérée et éventuelle promotion.Identifiant inconnu.
Consulter la positionPosition dans la file.Demande non en attente.
Afficher les placesCapacité et disponibilité.Ressource inconnue.
Créer une ressourceRessource accessible.Capacité négative ou nulle.

 

Atelier 2 — Choisir une structure

Associer chaque besoin à une structure et justifier le choix : historique d’annulation, utilisateurs par identifiant, tâches urgentes, relations sociales, demandes en attente, résultats triés.

Correction indicative

Besoin

Structure

Justification

Historique d’annulationPileDernière action annulée en premier.
Utilisateurs par identifiantTable de hachageRecherche exacte moyenne en O(1).
Tâches urgentesTas / file de prioritéExtraction du meilleur élément en O(log n).
Relations socialesGrapheModélisation naturelle des relations.
Demandes en attenteFileRespect de l’ordre d’arrivée.
Résultats triésTableau + triParcours et comparaison simples.

 

Atelier 3 — Décomposer un module trop long

Une fonction TraiterCommande lit une saisie, valide les données, modifie la structure, sauvegarde un fichier et affiche un message. Proposer un découpage modulaire.

Correction indicative

  ZONE DE PSEUDO-CODE — Découpage proposé

Procédure TraiterCommande(texte)
    commande ← Interface.Analyser(texte)
    erreurs ← Validation.Vérifier(commande)
    Si erreurs non vides Alors
         Interface.AfficherErreurs(erreurs)
        Retourner
    FinSi

    résultat ← Service.Exécuter(commande)
     Persistance.SauvegarderSiNécessaire(résultat)
     Interface.AfficherRésultat(résultat)

 

Atelier 4 — Construire une matrice de tests

Pour une fonction de recherche d’itinéraire, proposer au moins six tests appartenant à des catégories différentes.

Correction indicative

Test

Catégorie

Résultat attendu

Départ directement relié à l’arrivéeNormalChemin de longueur 1.
Plusieurs cheminsNormalChemin minimal en nombre d’arêtes.
Départ égal à arrivéeLimiteChemin contenant un sommet.
Réseau videLimiteErreur contrôlée.
Arrêt inconnuErronéMessage explicite.
Composantes distinctesDéfavorableAucun chemin.
Grand graphe creuxPerformanceTemps proche de O(n + m).

 

Atelier 5 — Analyser la complexité

Dans un réseau social représenté par listes d’adjacence, analyser : ajout d’un utilisateur, ajout d’une relation, calcul des composantes, tri des utilisateurs par degré.

Correction indicative

Opération

Complexité indicative

Hypothèse

Ajouter un utilisateurO(1) moyenDictionnaire pour les profils.
Ajouter une relationO(1) moyen ou O(degré)Ensemble de voisins ou liste à vérifier.
Calculer les composantesO(n + m)DFS ou BFS complet.
Calculer tous les degrésO(n + m)Somme des tailles des listes.
Trier par degréO(n log n)Tri comparatif des n utilisateurs.

 

Checklist de livraison

Vérification

État

Le besoin et le périmètre sont décrits.
Les fonctionnalités minimales sont toutes démontrables.
Les structures de données sont justifiées.
Le découpage en modules correspond au code.
Les pseudo-codes des opérations centrales sont fournis.
Le programme se lance selon les instructions du README.
Les erreurs et cas limites sont traités.
Les tests sont reproductibles et leurs résultats sont consignés.
La complexité des opérations principales est analysée.
Les mesures expérimentales utilisent des données comparables.
La documentation correspond à la version livrée.
La démonstration a été répétée sur un environnement propre.

 

Synthèse du chapitre

Étape

Question essentielle

Production attendue

AnalyserQuel problème et pour quels utilisateurs ?Spécifications et scénarios.
ModéliserQuelles données et quelles relations ?Structures et invariants.
ConcevoirComment répartir les responsabilités ?Modules, contrats et pseudo-codes.
ImplémenterComment traduire sans mélanger les couches ?Code lisible et versionné.
TesterComment prouver le comportement ?Jeux d’essai et rapports.
AnalyserQuel coût et quelles limites ?Complexités et mesures.
DocumenterComment transmettre et reproduire ?README, rapport et présentation.

 

Glossaire

Terme

Définition

Cahier des chargesDocument décrivant le besoin, le périmètre, les contraintes et les résultats attendus.
FonctionnalitéComportement observable offert à un utilisateur ou à un autre module.
InvariantPropriété qui doit rester vraie pendant toute la vie d’une structure.
ModuleUnité cohérente regroupant des responsabilités et une interface.
ContratPréconditions, postconditions, résultat et erreurs d’une opération.
PrototypeVersion minimale permettant de valider rapidement une idée.
RégressionDéfaut réintroduit dans une fonctionnalité auparavant correcte.
InstrumentationAjout de compteurs ou mesures pour observer un algorithme.
ReproductibilitéCapacité à obtenir les mêmes résultats avec le même protocole.
LivrableÉlément remis pour évaluation : code, rapport, tests ou présentation.
PérimètreEnsemble des fonctions incluses et exclues du projet.
Dette techniqueCoût futur créé par une solution rapide mais difficile à maintenir.

 

Auto-évaluation

Je peux…

Oui

À renforcer

formuler des fonctionnalités vérifiables à partir d’un besoin général ;
choisir une structure de données en fonction des opérations dominantes ;
découper une application en modules cohérents ;
rédiger un pseudo-code précis et indépendant du langage ;
concevoir des tests normaux, limites, erronés et de performance ;
analyser la complexité des opérations centrales ;
produire une documentation permettant de lancer et comprendre le projet ;
présenter et défendre mes choix algorithmiques ;

 

Conclusion

Le projet de synthèse constitue le passage d’algorithmes étudiés séparément à une application complète. Sa valeur repose sur la cohérence entre le besoin, les structures choisies, les algorithmes, les tests et la documentation.