Un corrigé pédagogique pour comprendre et justifier vos réponses. Les conseils de rédaction ne constituent pas un barème officiel détaillé.
Exercice 1 · 6 points
Modéliser les cartes et distribuer « 6 qui prend »
Marc programme « 6 qui prend » en Python, sans interface graphique. Le jeu possède 104 cartes numérotées de 1 à 104. Chaque carte porte des têtes de bœuf, notées TdB, qui sont des pénalités ; le but est d’en avoir le moins possible à la fin.
Partie A : classe Carte
Le constructeur reçoit une valeur entière de 1 à 104, stockée dans valeur. L’attribut entier TdB est calculé avec calcul_TdB, méthode qui n’exige aucun argument explicite autre que l’instance.
Question 1
#Écrire le constructeur de Carte.
Comprendre la correction
class Carte:
def __init__(self, valeur):
self.valeur = valeur
self.TdB = self.calcul_TdB()On stocke la valeur avant d’appeler le calcul, car la méthode en a besoin. calcul_TdB() renvoie le nombre de pénalités, que le constructeur affecte à l’attribut. Le sujet parle de « méthode de classe », mais l’interface décrite ici est une méthode d’instance utilisant self.
| Condition | TdB ajoutées |
|---|---|
| Valeur divisible par 11 | 5 |
| Dernier chiffre 0 | 3 |
| Dernier chiffre 5 | 2 |
| Aucune des trois conditions | 1 |
Les trois premières règles se cumulent ; par exemple 55 porte 7 TdB.
Question 2
#Écrire calcul_TdB pour calculer les pénalités selon les règles cumulatives.
Indice 1
Initialisez à 0, puis cumulez les critères indépendants.
Indice 2
La valeur 1 ne sert que si aucune règle spéciale ne s’applique.
Comprendre la correction
def calcul_TdB(self):
total = 0
if self.valeur % 11 == 0:
total += 5
if self.valeur % 10 == 0:
total += 3
if self.valeur % 10 == 5:
total += 2
if total == 0:
total = 1
return totalLes tests sont indépendants : 55 vérifie la divisibilité par 11 et la terminaison par 5, donc reçoit 5 + 2 = 7 pénalités. Une chaîne de elif ignorerait le second critère. La pénalité de base 1 n’est attribuée que si aucun critère n’a contribué, et ne s’ajoute pas aux autres.
Question 3
#Écrire est_superieure_a(self, autre), qui compare strictement les valeurs de deux cartes.
Comprendre la correction
def est_superieure_a(self, autre):
return self.valeur > autre.valeurOn compare les attributs numériques, pas les objets eux-mêmes. Deux valeurs égales donnent faux puisque la comparaison est stricte. La méthode fournie difference(autre) renverra quant à elle la valeur absolue de leur différence.
Partie B : classe Paquet
Le constructeur reçoit une liste de cartes et la stocke dans contenu. afficher affiche leurs valeurs ; ajouter_carte ajoute une carte.
class Paquet:
def __init__(self, L):
self.contenu = L
def afficher(self):
...
...
def ajouter_carte(self, carte):
...Question 4
#Compléter afficher et ajouter_carte de la classe Paquet.
Comprendre la correction
class Paquet:
def __init__(self, L):
self.contenu = L
def afficher(self):
for carte in self.contenu:
print(carte.valeur)
def ajouter_carte(self, carte):
self.contenu.append(carte)Le paquet contient des objets Carte, donc on affiche leur attribut valeur. append ajoute l’objet carte en fin de liste ; il ne faut pas ajouter seulement sa valeur, sinon le paquet mélangerait objets et entiers.
Question 5
#Écrire nombre_TdB, qui renvoie le total des pénalités des cartes d’un paquet.
Comprendre la correction
def nombre_TdB(self):
total = 0
for carte in self.contenu:
total += carte.TdB
return totalOn additionne les pénalités déjà calculées sur les objets Carte. Le retour reste après la boucle. Pour un paquet vide, le total est 0 ; pour les cartes 5, 10 et 55, il vaut 2 + 3 + 7 = 12.
Question 6
#Écrire distribuer(nbr), qui distribue 10 cartes par joueur, à tour de rôle, et renvoie les nbr paquets. La première carte du paquet va au premier joueur. Les cartes sont retirées du paquet source ; nbr est au maximum 10.
Indice
Un tour donne une carte à chaque joueur, et il faut dix tours.
Comprendre la correction
def distribuer(self, nbr):
paquets = [Paquet([]) for _ in range(nbr)]
for tour in range(10):
for joueur in range(nbr):
carte = self.contenu.pop(0)
paquets[joueur].ajouter_carte(carte)
return paquetsLa boucle extérieure fait les dix tours et l’intérieure sert successivement tous les joueurs. pop(0) enlève la première carte du paquet source. Avec deux joueurs et un paquet initial ordonné, le premier reçoit 1, 3, 5…19, et le second 2, 4, 6…20.
La compréhension crée un objet Paquet différent pour chaque joueur. [Paquet([])] * nbr serait incorrect : tous les joueurs partageraient le même paquet. La fonction suppose, comme la distribution du jeu, au moins 10 * nbr cartes disponibles ; un vrai service peut vérifier cette précondition avant de commencer.
Paquet propose aussi prendre_carte, qui demande une valeur jusqu’à choisir une carte présente, la retire et la renvoie ; trier classe les cartes par valeur croissante.
Partie C : joueurs et initialisation du plateau
class Joueur:
def __init__(self, nom, main):
self.nom = nom
self.main = main
self.cartes_ramassees = Paquet([])
self.penalite = 0ramasser_paquet ajoute un paquet aux cartes ramassées du joueur et augmente sa pénalité du total de TdB correspondant.
Question 7
#Instancier le joueur nommé « Joueur 1 », de main L[0], et affecter l’objet à J1.
Comprendre la correction
J1 = Joueur('Joueur 1', L[0])L[0] est déjà un Paquet : on le transmet directement. La chaîne « Joueur 1 » est le nom affichable, tandis que J1 est le nom de la variable Python.
from random import *
# Créer les104cartes par compréhension
jeu = [... for i in range(..., ...)]
shuffle(jeu)
jeu_initial = ...
distri = ...
Ordi = Joueur("Ordi", distri[0])
J1 = Joueur("J1", distri[1])Question 8
#Compléter les lignes 3, 7 et 9 de l’initialisation du jeu pour deux joueurs.
Comprendre la correction
from random import *
jeu = [Carte(i) for i in range(1, 105)]
shuffle(jeu)
jeu_initial = Paquet(jeu)
distri = jeu_initial.distribuer(2)
Ordi = Joueur("Ordi", distri[0])
J1 = Joueur("J1", distri[1])La borne 105 est exclue, donc les 104 valeurs de 1 à 104 sont créées. shuffle mélange la liste en place ; on ne doit pas affecter son retour, qui vaut None. Après distribution, 20 cartes ont quitté le paquet source, où il en reste 84.
Quelle carte coûte le plus cher ?Un atelier pour expérimenter
Faites varier une carte et le nombre de joueurs. Les pénalités sont décomposées règle par règle ; la distribution montre les dix tours d’un paquet ordonné pour rendre son fonctionnement visible.
Lire le résultat de l’expérience initiale
Carte55 : 7 tête(s) de bœuf
Les règles spéciales se cumulent. Le point de base apparaît seulement si aucune règle ne s’applique. La distribution ci-dessous est volontairement sans mélange pour montrer le tour de rôle.
| Tour | Joueur1 | Joueur2 |
|---|---|---|
| 1 | 1 | 2 |
| 2 | 3 | 4 |
| 3 | 5 | 6 |
| 4 | 7 | 8 |
| 5 | 9 | 10 |
| 6 | 11 | 12 |
| 7 | 13 | 14 |
| 8 | 15 | 16 |
| 9 | 17 | 18 |
| 10 | 19 | 20 |
Des règles cumulatives demandent des if indépendants. Une distribution à tour de rôle demande une boucle par tour puis une boucle par joueur, avec des objets de main distincts.
Revoir les notions de cet exercice
Exercice 2 · 6 points
SQL sur une collection de champignons et recherche dans une chaîne
Les deux parties sont indépendantes. Les caractéristiques, toxicités et recettes ci-dessous sont les données du sujet, à manipuler comme un modèle informatique. Elles ne doivent pas servir à identifier ni à décider de consommer un champignon.
Partie A : base relationnelle
Voici l’extrait fourni par SELECT * FROM champignon. Nom, lamelle et couleur sont des chaînes ; les tailles sont numériques et exprimées en centimètres.
| id | nom | id_ordre | lamelle | couleur | chapeau_min | chapeau_max | pied_min | pied_max |
|---|---|---|---|---|---|---|---|---|
| 1 | champignon de Paris | 1 | oui | blanc | 4 | 10 | 2 | 5 |
| 2 | champignon noir | 2 | non | noir | 2 | 10 | 0 | 0 |
| 3 | coprin chevelu | 1 | oui | blanc | 5 | 20 | 10 | 40 |
| 4 | bolet à pied rouge | 3 | non | jaune | 7 | 19 | 5 | 15 |
| 5 | amanite des Césars | 4 | oui | orange | 8 | 20 | 8 | 15 |
Question 1
#Mathilde cherche les noms des champignons ayant des lamelles et une couleur orange. Écrire la requête.
Comprendre la correction
SELECT nom
FROM champignon
WHERE lamelle = 'oui' AND couleur = 'orange';Les deux conditions sont nécessaires simultanément. On conserve la casse des valeurs de l’extrait : oui est une chaîne et non un booléen SQL.
Question 2
#Romain cherche un champignon sans pied et dont le chapeau mesure 15 cm. Écrire la requête donnant les noms possibles.
SQLTester une mesure dans l’intervalle du modèleÉcrivez votre solution et mettez-la à l’épreuve
Renvoyez les noms des lignes du modèle décrivant un champignon sans pied et dont la plage de diamètre du chapeau contient 15 cm. Ces données scolaires ne doivent pas servir à identifier ou consommer un champignon réel.
SELECT ...
FROM ...
WHERE ...;Les cas de test proposés :
- Extrait officiel des cinq champignons : Les lignes reprennent le tableau officiel. Le seul champignon sans pied de l’extrait a un chapeau de 2 à 10 cm ; aucune ligne ne convient pour 15 cm.
- Cas complémentaire : les bornes font partie de la plage : Jeu complémentaire pédagogique, distinct des données officielles. Noms artificiels de test.15 peut être égal au minimum ou au maximum. Un intervalle de pied 0 à 2 ne signifie pas une absence de pied.
Indice
Une mesure appartient à un intervalle fermé si elle satisfait ses deux bornes.
Comprendre la correction
SELECT nom
FROM champignon
WHERE pied_min = 0 AND pied_max = 0
AND chapeau_min <= 15 AND chapeau_max >= 15;Une dimension mesurée doit appartenir à l’intervalle stocké : on ne cherche pas seulement un maximum ou un minimum égal à 15. « Sans pied » est ici représenté par un intervalle de longueur nulle 0 à 0. Dans l’extrait, le champignon noir est sans pied, mais son chapeau ne dépasse pas 10 cm : aucune des cinq lignes ne satisfait l’ensemble.
| ordre.id | nom | classe |
|---|---|---|
| 1 | agaricales | agaricomycètes |
| 2 | trémellales | phragmabasidiomycètes |
| 3 | bolétales | agaricomycètes |
| 4 | amanitales | agaricomycètes |
| 5 | cantharellales | agaricomycètes |
| 6 | polyporales | basidiomycètes |
| 7 | clavariales | homobasidiomycètes |
| 8 | tricholomatales | agaricomycètes |
Question 3
#Donner la clé étrangère de champignon qui référence ordre.id.
Comprendre la correction
id_ordre est la clé étrangère. Par exemple, la valeur 4 d’une ligne de champignon renvoie à l’ordre amanitales.
Question 4
#Écrire la requête donnant les noms des champignons de la classe agaricomycètes.
Comprendre la correction
SELECT champignon.nom
FROM champignon JOIN ordre ON champignon.id_ordre = ordre.id
WHERE ordre.classe = 'agaricomycètes';La classe appartient à la table ordre, tandis que le nom recherché appartient à champignon. La jointure suit l’identifiant d’ordre ; on qualifie le nom de champignon pour éviter l’ambiguïté avec ordre.nom.
Question 5
#Ajouter avec l’identifiant 56 l’amanite solitaire : blanc, ordre amanitales, avec lamelles, chapeau de 6 à 20 cm et pied de 4 à 10 cm.
Comprendre la correction
INSERT INTO champignon
(id, nom, id_ordre, lamelle, couleur, chapeau_min, chapeau_max, pied_min, pied_max)
VALUES (56, 'amanite solitaire', 4, 'oui', 'blanc', 6, 20, 4, 10);On utilise l’identifiant 4 de l’ordre amanitales, et non son nom dans la colonne étrangère. Nommer les colonnes explicite l’ordre des valeurs et évite d’inverser les bornes du chapeau et du pied.
On ajoute l’attribut id_toxicite à champignon et la relation toxicite :
| id_tox | type | effets (données du sujet) |
|---|---|---|
| 1 | très toxique | Entraînant la mort |
| 2 | toxique | Entraînant des problèmes digestifs ou nerveux |
| 3 | à rejeter | Champignons suspects ou ayant un mauvais goût |
| 4 | comestible | Champignons pouvant être consommés |
Question 6
#Écrire le schéma relationnel à trois tables avec clés primaires soulignées et clés étrangères précédées de #.
Comprendre la correction
champignon(id, nom, #id_ordre, lamelle, couleur, chapeau_min, chapeau_max, pied_min, pied_max, #id_toxicite)
ordre(id, nom, classe)
toxicite(id_tox, type, effets)
id_ordre référence ordre.id et id_toxicite référence toxicite.id_tox. Une clé étrangère n’est pas automatiquement unique : plusieurs champignons peuvent partager la même toxicité ou le même ordre.
Le PDF indique : « Une erreur s’est glissée dans cette table : le champignon de nom amanite citrine est très toxique car son ingestion peut entraîner la mort. » Cette assertion est une donnée à traiter pour la question SQL, et non une règle d’identification ou de consommation.
Question 7
#Le sujet demande de classer la ligne « amanite citrine » dans la toxicité « très toxique ». Écrire la requête corrigeant sa valeur dans champignon.
Comprendre la correction
UPDATE champignon
SET id_toxicite = 1
WHERE nom = 'amanite citrine';La valeur 1 référence la catégorie demandée dans la table toxicite. On modifie la référence de cette ligne, pas le libellé de toute la catégorie. Cette instruction applique la donnée de l’exercice ; elle ne constitue pas une affirmation validée de toxicologie.
Question 8
#Écrire la requête donnant les noms des champignons d’ordre amanitales et de toxicité très toxique.
Comprendre la correction
SELECT champignon.nom
FROM champignon
JOIN ordre ON champignon.id_ordre = ordre.id
JOIN toxicite ON champignon.id_toxicite = toxicite.id_tox
WHERE ordre.nom = 'amanitales' AND toxicite.type = 'très toxique';Les deux jointures rendent les libellés disponibles. Le filtre exige à la fois l’ordre et la toxicité ; on ne remplace pas leurs noms par des identifiants supposés constants lorsque le schéma permet de les chercher.
Partie B : objets et recherche textuelle
Quentin associe au lactaire délicieux : localisation sous les pins, saison été, recette « lactaires grillés à l’huile d’olive », cuisson «12 minutes à feu moyen ». Il stocke ces informations ainsi :
class Champignon:
def __init__(self, nom, lieu, saison, recette, cuisson):
self.nom = nom
self.localisation = lieu
self.saison = saison
self.recette = recette
self.cuisson = cuissonchampignon1 = Champignon(
"Lactaire délicieux", "Sous les pins", "été",
"Lactaires grillés à l’huile d’olive", "12 minutes à feu moyen"
)Toutes les instances sont placées dans la liste liste_champi.
for e in liste_champi:
if ... == 'été':
print(...)Question 9
#Compléter le programme qui affiche les noms des objets de liste_champi dont la saison est été.
Comprendre la correction
for e in liste_champi:
if e.saison == 'été':
print(e.nom)Chaque élément est un objet, donc ses champs s’accèdent avec le point. La comparaison porte sur la saison, tandis que l’affichage porte sur le nom.
for c in liste_champi:
if c.nom == 'Lactaire délicieux':
return c.cuisson == 'feu moyen'Question 10
#Pourquoi le programme ne donne-t-il pas le résultat attendu pour une cuisson à feu moyen ?
Comprendre la correction
La valeur de c.cuisson est '12 minutes à feu moyen', pas exactement 'feu moyen'. L’égalité compare les chaînes entières et donne donc faux, même si la seconde est incluse dans la première.
Le fragment imprimé utilise aussi return hors de toute fonction : copié seul au niveau du module, il provoque une erreur de syntaxe. L’explication de la comparaison suppose qu’il était placé dans une fonction, comme le laisse entendre le commentaire du sujet.
La fonction fournie vérifie par exemple recherche_textuelle('dans une forêt', 'forêt') == True et recherche_textuelle('près de la mer', 'mare') == False.
Question 11
#Corriger le programme avec recherche_textuelle(texte, mot), qui indique si le texte contient le mot ou l’expression cherchée.
Comprendre la correction
for c in liste_champi:
if c.nom == 'Lactaire délicieux':
print(recherche_textuelle(c.cuisson, 'feu moyen'))La cuisson complète est le texte à parcourir ; « feu moyen » est l’expression recherchée. Cette version de script affiche le booléen. Si l’on place le fragment dans une fonction, on peut retourner ce même appel au lieu de l’afficher.
Une mesure entre deux bornesUn atelier pour expérimenter
Faites varier le diamètre de chapeau et la présence d’un pied. L’atelier filtre uniquement les cinq lignes de l’extrait pour montrer comment une requête compare un intervalle. Il ne sert pas à identifier un champignon réel.
Lire le résultat de l’expérience initiale
0 ligne(s) correspondante(s) dans l’extrait
La mesure doit être supérieure ou égale au minimum et inférieure ou égale au maximum. Un résultat vide signifie seulement qu’aucune ligne de cet extrait ne satisfait les filtres.
| Nom du modèle | Intervalle chapeau | Intervalle pied | Satisfait les deux filtres |
|---|---|---|---|
| champignon de Paris | 4 à 10 | 2 à 5 | Non |
| champignon noir | 2 à 10 | 0 à 0 | Non |
| coprin chevelu | 5 à 20 | 10 à 40 | Non |
| bolet à pied rouge | 7 à 19 | 5 à 15 | Non |
| amanite des Césars | 8 à 20 | 8 à 15 | Non |
Un test d’appartenance à un intervalle combine deux inégalités. Les valeurs sélectionnées restent celles d’un jeu de données limité, pas une identification du monde réel.
Revoir les notions de cet exercice
Exercice 3 · 8 points
Transformer des mots avec un parcours en largeur
On dispose de mots de quatre lettres : par exemple gars, grue, mars, mors, ours, purs, durs. Deux mots sont voisins si l’on peut changer exactement une lettre pour passer de l’un à l’autre, sans tenir compte de l’ordre des lettres. Mars et mors sont voisins ; mors et ours aussi ; grue et ours nécessitent deux remplacements.
On veut relier un mot de départ à un mot final avec le minimum de voisins intermédiaires. Exemple : mars, mors, ours. Le sujet suppose toujours qu’un chemin existe. Un graphe représente les mots comme sommets et les voisinages comme arêtes.
Partie A : structures adaptées
Question 1
#Décrire le fonctionnement d’une pile.
Comprendre la correction
Une pile suit le principe LIFO, dernier entré, premier sorti. Empiler ajoute au sommet ; dépiler retire et renvoie le sommet. Si on empile A puis B puis C, on dépile C, puis B, puis A : cette inversion d’ordre servira à reconstruire le chemin.
Question 2
#Décrire le fonctionnement d’une file.
Comprendre la correction
Une file suit FIFO, premier entré, premier sorti. Enfiler ajoute en queue ; défiler retire la tête. A, B et C enfilés dans cet ordre ressortent A, B, C. Cela permet au parcours en largeur d’explorer les sommets dans l’ordre de leur découverte.
Question 3
#Pourquoi un graphe non orienté convient-il ?
Comprendre la correction
Le remplacement de lettre est réversible : si A peut devenir B en un changement, B peut devenir A en rétablissant la lettre. Le voisinage est donc symétrique ; une arête sans orientation décrit cette relation.
Question 4
#Dessiner le graphe pour gars, mars, mors, ours et purs.
Comprendre la correction
Lire les connexions du schéma
- gars relié à mars
- mars relié à mors
- mors relié à ours
- ours relié à purs
Il comporte les quatre arêtes gars-mars, mars-mors, mors-ours et ours-purs. Toute autre paire exige au moins deux changements, donc n’a pas d’arête directe. Un graphe doit conserver aussi les sommets, pas seulement une liste de transitions.
Partie B : calculer le voisinage
La distance est le minimum de lettres à remplacer sans imposer leur position. Deux mots sont voisins si leur distance vaut 1. TAB_MOTS est une variable globale contenant des mots de quatre caractères.
def chaine_vers_tab(mot):
tab_lettres = ...
for ... in ...:
tab_lettres....
return tab_lettresQuestion 5
#Compléter chaine_vers_tab(mot), qui convertit un mot de quatre caractères en liste de lettres.
Comprendre la correction
def chaine_vers_tab(mot):
tab_lettres = []
for lettre in mot:
tab_lettres.append(lettre)
return tab_lettresLa boucle conserve les caractères dans leur ordre initial et leurs répétitions. Pour ours, on obtient ['o', 'u', 'r', 's']. Même si le calcul de distance ignore ensuite l’ordre, il doit encore conserver le nombre d’occurrences de chaque lettre.
Question 6
#Expliquer pourquoi la fonction donnée calcule la distance entre deux mots de quatre caractères.
Indice
remove supprime une occurrence, ce qui conserve la multiplicité des lettres.
Comprendre la correction
def distance(mot1, mot2):
tab = chaine_vers_tab(mot1)
for lettre in mot2:
if lettre in tab:
tab.remove(lettre)
return len(tab)La liste commence avec toutes les occurrences des lettres du premier mot. Chaque lettre du second retire au plus une occurrence identique encore disponible. Après ce couplage, les lettres restantes du premier mot n’ont pas d’équivalent : il faut les remplacer. Comme les mots ont la même longueur, le nombre de lettres manquantes de l’autre côté est identique.
Pour grue et ours, on apparie r et u ; g et e restent, donc la distance vaut 2. Avec des répétitions, remove ne retire qu’une occurrence, ce qui est essentiel. Un ensemble de lettres donnerait des réponses fausses. Deux anagrammes ont ici une distance 0, même si leurs positions diffèrent.
def renvoie_voisins(mot):
tab_voisins = ...
for voisin_possible in ...:
if ...:
tab_voisins....
return ...Question 7
#Compléter renvoie_voisins(mot), qui liste les mots de TAB_MOTS voisins du mot donné.
Comprendre la correction
def renvoie_voisins(mot):
tab_voisins = []
for voisin_possible in TAB_MOTS:
if distance(mot, voisin_possible) == 1:
tab_voisins.append(voisin_possible)
return tab_voisinsOn teste chaque candidat avec la distance égale à 1. Une distance 0 n’est pas admise : le mot lui-même, ainsi que ses anagrammes selon cette définition, ne sont pas voisins par un remplacement exactement. Le résultat est une nouvelle liste, dans l’ordre de TAB_MOTS.
Partie C : chercher un plus court chemin
File propose est_vide, defiler et enfiler. Pile propose est_vide, depiler et empiler. Le programme fourni est :
def dic_parent(mot_depart, mot_final):
file_voisins = File()
parent = {mot_depart: None}
mot = mot_depart
file_voisins.enfiler(mot)
while not file_voisins.est_vide() and not mot == mot_final:
mot = file_voisins.defiler()
for voisin in renvoie_voisins(mot):
if not voisin in parent:
parent[voisin] = mot
file_voisins.enfiler(voisin)
return parentVoisins donnés : mars → gars, mors ; gars → mars ; mors → mars, ours ; ours → mors, purs. Initialement parent vaut {'mars': None} et la file contient mars. Au premier tour, mars est retiré, gars et mors sont ajoutés avec parent mars ; la file contient gars puis mors. Au deuxième tour, gars est retiré, mars déjà connu est ignoré ; seule mors reste en file.
Question 8
#Poursuivre la trace de dic_parent('mars', 'ours') après les deux premiers tours, jusqu’à la fin.
Indice
Le test d’arrêt se fait avant le tour suivant, après le traitement des voisins.
Comprendre la correction
| Tour | Mot défilé | Mise à jour de parent | File après traitement |
|---|---|---|---|
| 3 | mors | Ajout ours : mors | [ours] |
| 4 | ours | Ajout purs : ours | [purs] |
Au tour 3, mars est déjà connu ; seul ours est découvert. Le tour 4 défile ours, puis traite quand même ses voisins avant de retester la condition de boucle : mors est connu et purs est ajouté. Le test suivant voit mot == mot_final et arrête la boucle.
{'mars': None, 'gars': 'mars', 'mors': 'mars',
'ours': 'mors', 'purs': 'ours'}La file conserve donc purs à la fin. Le dictionnaire contient des sommets explorés qui ne sont pas sur le chemin final, comme gars et purs. Il ne faut pas le confondre avec la seule liste mars-mors-ours.
def renvoie_pile(parent, mot_final):
ma_pile = Pile()
mot = mot_final
while mot != ...:
ma_pile....
mot = ...
return ma_pileQuestion 9
#Compléter renvoie_pile(parent, mot_final). Le mot final est empilé d’abord, et le sommet final de la pile doit être le mot de départ.
PythonRemonter un chemin sans perdre le mot de départÉcrivez votre solution et mettez-la à l’épreuve
Écrivez renvoie_pile(parent, mot_final). Le dictionnaire parent provient du parcours en largeur : il associe chaque mot découvert à son prédécesseur, et le mot de départ à None. Le mot final a été atteint. Empilez d’abord ce mot final, puis ses prédécesseurs jusqu’au départ inclus. Renvoyez l’objet Pile ; quand on le dépilera, on doit lire le chemin du départ à l’arrivée. Ne modifiez pas parent.
def renvoie_pile(parent, mot_final):
# À vous de jouer
passLes cas de test proposés :
- Le chemin de l’exemple : L’ordre d’empilement est inversé par l’ordre de dépilement.
- Départ et arrivée confondus : Le départ lui-même doit être empilé avant de lire son parent
None. - Un seul lien : Deux sommets demandent deux éléments dans la pile, pas seulement l’arrivée.
- Ignorer les branches qui ne mènent pas au but : On suit une chaîne de parents ; parcourir toutes les clés ajouterait à tort murs.
- Le dictionnaire reste disponible : D’autres reconstructions doivent pouvoir réutiliser la même exploration.
Indice
Le départ a pour parentNone.
Comprendre la correction
def renvoie_pile(parent, mot_final):
ma_pile = Pile()
mot = mot_final
while mot is not None:
ma_pile.empiler(mot)
mot = parent[mot]
return ma_pileOn remonte le parent de chaque mot jusqu’à None, qui marque le prédécesseur du départ. Pour ours, on empile ours, puis mors, puis mars. Ne pas arrêter avant d’empiler le départ : il doit figurer dans le chemin.
def construit_chemin(ma_pile):
tab = ...
while ...:
mot = ...
tab....
return tabQuestion 10
#Compléter construit_chemin(ma_pile), qui renvoie la liste des mots dans le bon ordre.
Comprendre la correction
def construit_chemin(ma_pile):
tab = []
while not ma_pile.est_vide():
mot = ma_pile.depiler()
tab.append(mot)
return tabLe sommet est le départ. Dépiler fournit donc mars, mors, ours et remet la chaîne de parents dans l’ordre du trajet. La pile est consommée par cette fonction ; le tableau obtenu garde les mots.
Question 11
#Coder chercher_chemin(mot_depart, mot_final) à l’aide des fonctions précédentes.
Comprendre la correction
def chercher_chemin(mot_depart, mot_final):
parent = dic_parent(mot_depart, mot_final)
ma_pile = renvoie_pile(parent, mot_final)
return construit_chemin(ma_pile)Chaque fonction a une responsabilité : explorer, remonter les parents, remettre le chemin dans l’ordre. Le parcours en largeur découvre les sommets à distance croissante, donc le premier parent enregistré pour le but donne un plus court chemin dans ce graphe non pondéré.
Si départ et arrivée sont identiques, la pile contient ce seul mot et le résultat est une liste de longueur 1. Si aucun chemin n’existait, il faudrait tester la présence du but dans parent avant la reconstruction ; le sujet garantit son existence.
Suivez la file et reconstruisez le cheminUn atelier pour expérimenter
Choisissez départ et arrivée parmi les cinq mots, puis le nombre d’étapes du parcours. La simulation suit exactement le code fourni, y compris le traitement des voisins du mot final au dernier tour.
Lire le résultat de l’expérience initiale
mars → mors → ours
Le dictionnaire sert aussi de marqueur de découverte : un sommet connu n’est plus enfilé. La file conserve l’ordre des distances, la pile remet ensuite les parents dans le sens du trajet.
| Tour | Mot défilé | Nouveaux parents | File après le tour |
|---|---|---|---|
| 1 | mars | gars ← mars, mors ← mars | gars, mors |
| 2 | gars | Aucun | mors |
| 3 | mors | ours ← mors | ours |
| 4 | ours | purs ← ours | purs |
La file garantit l’exploration par distance ; le dictionnaire mémorise une seule découverte par sommet ; la pile inverse la remontée des parents pour produire le chemin.
Du sujet à la méthode
Votre prochaine séance de révision
- Pour les règles de cartes, testez 55 : cet exemple distingue immédiatement une somme de critères d’une alternative exclusive.
- Pour SQL, traduisez chaque intervalle par deux inégalités et chaque lien entre tables par une référence.
- Dans la trace BFS, respectez le moment où la condition d’arrêt est évaluée : le mot final peut encore ajouter un voisin avant la fin.
Retrouver ces notions dans d’autres sujets
Toutes les annales de NSI · Le guide pour préparer le bac NSI 2027
Énoncé : sujet 25-NSIJ2PO1 (PDF). Corrigé et explications pédagogiques proposés par Sofien.
