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é.
Application
Boutique de smoothies et recherche d’alternatives
La maison des lycéens veut afficher les smoothies réalisables avec les fruits du jour et proposer des alternatives aux recettes indisponibles. Chaque recette possède trois fruits. Une Boutique_smoothie conserve la liste des ingrédients disponibles et le dictionnaire des dix recettes. Le score de proximité compte les fruits communs. Pour correspondre aux tests fournis, une alternative doit être réalisable, différente de la recette de référence et partager au moins un fruit avec elle.
| Recette | Fruits |
|---|---|
| Tropical | Mangue, Ananas, Banane |
| Rouge | Fraise, Framboise, Cerise |
| Vert | Kiwi, Pomme verte, Menthe |
| Agrume | Orange, Citron, Pamplemousse |
| Exotique | Papaye, Fruit de la passion, Noix de coco |
| Tropical citron | Mangue, Ananas, Citron |
| Rouge kiwi | Fraise, Framboise, Kiwi |
| Exotique rouge | Papaye, Fraise, Fruit de la passion |
| Vert citron | Kiwi, Pomme verte, Citron |
| Soleil couchant | Mangue, Fraise, Pamplemousse |
Le dossier comporte le sujet et les fichiers listés dans les téléchargements. Les codes de départ sont reproduits ci-dessous. Travaillez sur une copie. Les appels professeur signalés dans les questions servent à présenter votre démarche ; vous pouvez aussi demander de l’aide en cas de difficulté.
Code fourni : smoothie.py
class Boutique_smoothie:
def __init__(self, liste_fruits_disponibles):
self.liste_fruits_disponibles = liste_fruits_disponibles
self.db_smoothies = {
"Tropical": ["Mangue", "Ananas", "Banane"],
"Rouge": ["Fraise", "Framboise", "Cerise"],
"Vert": ["Kiwi", "Pomme verte", "Menthe"],
"Agrume": ["Orange", "Citron", "Pamplemousse"],
"Exotique": ["Papaye", "Fruit de la passion", "Noix de coco"],
"Tropical citron": ["Mangue", "Ananas", "Citron"],
"Rouge kiwi": ["Fraise", "Framboise", "Kiwi"],
"Exotique rouge": ["Papaye", "Fraise", "Fruit de la passion"],
"Vert citron": ["Kiwi", "Pomme verte", "Citron"],
"Soleil couchant": ["Mangue", "Fraise", "Pamplemousse"]
}
##### QUESTION 1 #####
def smoothie_possible(self, nom_smoothie):
"""Retourne True si le smoothie peut être préparé avec les fruits disponibles, False sinon."""
pass # à remplacer par le code la méthode
##### QUESTION 2 #####
def liste_smoothies_possibles(self):
"""Retourne la liste des smoothies pouvant être préparés avec les fruits disponibles."""
pass # à remplacer par le code la méthode
def score_proximité(self, nom1, nom2):
"""Retourne le nombre de fruits communs entre deux smoothies."""
nb = 0
fruits1 = self.db_smoothies[nom1]
fruits2 = self.db_smoothies[nom2]
for fruit in fruits1:
if fruit in fruits2:
nb += 1
return nb
# Question 4
def plus_proche_possible(self, nom_smoothie_ref):
"""Retourne le nom du smoothie le plus proche de nom_smoothie_ref en termes de fruits communs parmi les smoothies possibles.
En cas d'égalité, retourne le premier trouvé.
"""
max_communs = 0
smoothie_proche = None
for nom_smoothie in self.db_smoothies:
nb_communs = self.score_proximité(nom_smoothie_ref, nom_smoothie)
if nb_communs > max_communs:
max_communs = nb_communs
smoothie_proche = nom_smoothie
return smoothie_proche
def affichage_possibles(self):
"""Affiche les smoothies possibles."""
smoothies = self.liste_smoothies_possibles()
print("Smoothies possibles avec les fruits disponibles :")
for smoothie in smoothies:
print(smoothie)
print("Alternative aux autres smoothies :")
for smoothie in self.db_smoothies:
if smoothie not in smoothies:
proche = self.plus_proche_possible(smoothie)
if proche != None:
print(f"Pour le smoothie {smoothie}, essayez {proche}.")
else:
print(
f"Pour le smoothie {smoothie}, aucun smoothie proche disponible.")
# ========= Fonctions de test ==================
def test_smoothie_possible():
boutique = Boutique_smoothie(
["Mangue", "Ananas", "Banane", "Fraise", "Citron"])
assert boutique.smoothie_possible("Tropical") == True
assert boutique.smoothie_possible("Rouge") == False
def test_liste_smoothies_possibles():
boutique1 = Boutique_smoothie(
["Mangue", "Ananas", "Banane", "Fraise", "Citron"])
boutique2 = Boutique_smoothie(
["Fraise", "Framboise", "Cerise", "Kiwi", "Orange", "Citron", "Pamplemousse"])
boutique3 = Boutique_smoothie(["Orange", "Mangue", "Papaye"])
assert boutique1.liste_smoothies_possibles() == [
"Tropical", "Tropical citron"]
assert boutique2.liste_smoothies_possibles() == [
"Rouge", "Agrume", "Rouge kiwi"]
assert boutique3.liste_smoothies_possibles() == []
##### QUESTION 3 #####
def test_score_proximité():
# À compléter
pass
def test_plus_proche_possible():
boutique = Boutique_smoothie(
["Mangue", "Ananas", "Banane", "Fraise", "Citron", "Kiwi", "Pomme verte"])
smoothie_proche = boutique.plus_proche_possible("Tropical")
assert smoothie_proche == "Tropical citron"
smoothie_proche2 = boutique.plus_proche_possible("Exotique")
assert smoothie_proche2 == None
# ======== Lancement des tests ========
test_smoothie_possible()
test_liste_smoothies_possibles()
test_plus_proche_possible()
# Question 5
Question 1
#Écrire smoothie_possible : recevoir le nom d’un smoothie et renvoyer un booléen indiquant si tous ses ingrédients sont disponibles.
Indice
Chercher d’abord un ingrédient qui empêche la réalisation.
Comprendre la correction
def smoothie_possible(self, nom_smoothie):
for fruit in self.db_smoothies[nom_smoothie]:
if fruit not in self.liste_fruits_disponibles:
return False
return TrueCette fonction est une méthode : elle reçoit self puis le nom. Le premier fruit manquant suffit à répondre False. True doit rester après la boucle, car trouver un premier fruit disponible ne suffit pas. On suppose un nom présent dans le catalogue, conformément aux appels du sujet.
Question 2
#Écrire liste_smoothies_possibles, sans paramètre autre que self, qui renvoie la liste des recettes possibles.
Comprendre la correction
def liste_smoothies_possibles(self):
resultat = []
for nom in self.db_smoothies:
if self.smoothie_possible(nom):
resultat.append(nom)
return resultatOn réutilise la méthode précédente, puis on conserve les noms dans l’ordre du dictionnaire. Une boutique sans recette réalisable doit renvoyer [], pas None. Lancer test_smoothie_possible et test_liste_smoothies_possibles.
Question 3
#Compléter test_score_proximité avec des tests pertinents pour le nombre de fruits communs.
Indice
Deux recettes identiques ont trois ingrédients communs.
Comprendre la correction
def test_score_proximité():
b = Boutique_smoothie([])
assert b.score_proximité('Tropical', 'Tropical') == 3
assert b.score_proximité('Tropical', 'Tropical citron') == 2
assert b.score_proximité('Tropical', 'Soleil couchant') == 1
assert b.score_proximité('Tropical', 'Rouge') == 0
for a in b.db_smoothies:
for autre in b.db_smoothies:
assert b.score_proximité(a, autre) == b.score_proximité(autre, a)Les quatre premiers tests couvrent tous les scores possibles :3,2,1 et 0. Le dernier vérifie la symétrie : inverser les deux recettes ne doit pas changer leur nombre de fruits communs. Le stock n’intervient pas dans ce calcul ; il sert seulement à filtrer les recettes réalisables.
Question 4
#Observer l’échec avec test_plus_proche_possible, identifier le problème dans plus_proche_possible, proposer une démarche et corriger.
PythonTrouver une vraie alternative réalisableÉcrivez votre solution et mettez-la à l’épreuve
Complétez plus_proche_possible dans la classe fournie. Parmi les autres recettes réalisables, renvoyez celle qui partage le plus de fruits avec la référence ; son score doit être strictement positif. En cas d’égalité, gardez la première recette du catalogue. Renvoyez None sans alternative. Le catalogue et les méthodes auxiliaires du sujet sont déjà présents.
class Boutique_smoothie:
def __init__(self, liste_fruits_disponibles):
self.liste_fruits_disponibles = liste_fruits_disponibles
self.db_smoothies = {
"Tropical": ["Mangue", "Ananas", "Banane"],
"Rouge": ["Fraise", "Framboise", "Cerise"],
"Vert": ["Kiwi", "Pomme verte", "Menthe"],
"Agrume": ["Orange", "Citron", "Pamplemousse"],
"Exotique": ["Papaye", "Fruit de la passion", "Noix de coco"],
"Tropical citron": ["Mangue", "Ananas", "Citron"],
"Rouge kiwi": ["Fraise", "Framboise", "Kiwi"],
"Exotique rouge": ["Papaye", "Fraise", "Fruit de la passion"],
"Vert citron": ["Kiwi", "Pomme verte", "Citron"],
"Soleil couchant": ["Mangue", "Fraise", "Pamplemousse"]
}
def smoothie_possible(self, nom_smoothie):
for fruit in self.db_smoothies[nom_smoothie]:
if fruit not in self.liste_fruits_disponibles:
return False
return True
def score_proximité(self, nom1, nom2):
"""Retourne le nombre de fruits communs entre deux smoothies."""
nb = 0
fruits1 = self.db_smoothies[nom1]
fruits2 = self.db_smoothies[nom2]
for fruit in fruits1:
if fruit in fruits2:
nb += 1
return nb
def plus_proche_possible(self, nom_smoothie_ref):
# Complétez cette méthode
pass
Les cas de test proposés :
- Exemple fourni : La recette de référence, pourtant réalisable, doit être exclue.
- Possible ne signifie pas proche : Le test officiel exclut aussi les alternatives de score nul.
- Stock vide : Un score élevé ne rend pas une recette réalisable.
- Alternative malgré une référence impossible : La référence sert à comparer les goûts, sans devoir être elle-même disponible.
- Première recette en cas d’égalité : Ce petit catalogue complémentaire crée une égalité de score 2 pour vérifier la règle du sujet.
Indice
Vérifier le domaine des candidats avant de chercher le maximum.
Comprendre la correction
Le code fourni cherche parmi toutes les recettes, même irréalisables, et inclut la référence elle-même, dont le score 3 gagne systématiquement. Le test attend pourtant Tropical citron pour Tropical, bien que Tropical soit disponible. Il impose donc une véritable autre recette. Le second test attend None pour Exotique lorsque toutes les recettes possibles ont un score nul. La correction conserve ces conventions explicites :
def plus_proche_possible(self, nom_smoothie_ref):
max_communs = 0
smoothie_proche = None
for nom in self.db_smoothies:
if nom != nom_smoothie_ref and self.smoothie_possible(nom):
nb = self.score_proximité(nom_smoothie_ref, nom)
if nb > max_communs:
max_communs = nb
smoothie_proche = nom
return smoothie_procheLe test strict nb>max_communs préserve la première recette en cas d’égalité. Initialiser le maximum à 0 exclut les recettes sans fruit commun. Si l’on définissait au contraire une alternative comme tout maximum, même nul, le second test serait incompatible : cette nuance doit être expliquée à l’oral.
test_plus_proche_possible()
assert Boutique_smoothie([]).plus_proche_possible('Tropical') is NoneLa recherche comporte deux décisions qu’il faut pouvoir expliquer séparément. D’abord, une recette est-elle admissible : différente de la référence et réalisable avec le stock ? Ensuite, son score améliore-t-il le meilleur score déjà rencontré ? Si l’on mélange ces décisions, une recette impossible peut devenir provisoirement gagnante et empêcher ensuite une vraie alternative d’être retenue. Après chaque tour, smoothie_proche désigne la première recette admissible ayant le plus grand score strictement positif parmi celles déjà visitées. Cette propriété justifie à la fois le résultat final et la règle d’égalité.
Choisir une vraie alternativeUn atelier pour expérimenter
Choisissez une réponse puis confrontez votre intuition à l’explication. Vous pouvez modifier vos choix.
Lire les réponses et leurs explications
- Une recette a le meilleur score mais manque de fruits. La retenir ?
Non, elle doit être réalisable.. On filtre d’abord, puis on maximise.
- Pourquoi utiliser > plutôt que≥ dans la mise à jour ?
Pour conserver le premier maximum.. Une égalité ne remplace pas le candidat déjà choisi.
Appuyez votre explication sur les valeurs et les conditions exactes du programme.
Question 5
#Créer une boutique avec Mangue, Ananas, Banane, Fraise, Citron, Kiwi et Pomme verte, puis afficher les smoothies réalisables.
Comprendre la correction
b = Boutique_smoothie(['Mangue','Ananas','Banane','Fraise',
'Citron','Kiwi','Pomme verte'])
for nom in b.liste_smoothies_possibles():
print(nom)L’affichage est Tropical, Tropical citron, Vert citron, dans cet ordre. Vert n’est pas possible car Menthe manque ; Rouge kiwi manque de Framboise. La méthode affichage_possibles fournie peut aussi afficher les alternatives, une fois la correction précédente effectuée.
Composez le stock du jourUn atelier pour expérimenter
Retirez Banane ou Citron du stock de la question 5. Choisissez une recette recherchée et voyez les recettes réalisables, leur score et l’alternative retenue.
Lire le résultat de l’expérience initiale
Alternative : Tropical citron.
Le filtrage garantit la faisabilité ; la recherche du maximum s’applique ensuite aux autres recettes.
| Recette réalisable | Fruits communs | Rôle |
|---|---|---|
| Tropical | 3 | Référence exclue |
| Tropical citron | 2 | Candidate |
| Vert citron | 0 | Candidate |
Une recherche de maximum commence par définir les candidats admissibles et la règle d’égalité.
Du sujet à la méthode
Votre prochaine séance de révision
- Séparer possibilité, score et recherche du meilleur candidat.
- Lire les tests : ils précisent parfois des conventions implicites de l’énoncé.
Retrouver ces notions dans d’autres sujets
Toutes les annales de NSI · Le guide pour préparer le bac NSI 2027
Énoncé : sujet 26_BCG_NSI_6 (PDF). Corrigé et explications pédagogiques proposés par Sofien.
