Épreuve pratique · 2026 · Sujet 6

Bac NSI pratique 2026 sujet 6 : 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.

Dans ce sujet

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.

RecetteFruits
TropicalMangue, Ananas, Banane
RougeFraise, Framboise, Cerise
VertKiwi, Pomme verte, Menthe
AgrumeOrange, Citron, Pamplemousse
ExotiquePapaye, Fruit de la passion, Noix de coco
Tropical citronMangue, Ananas, Citron
Rouge kiwiFraise, Framboise, Kiwi
Exotique rougePapaye, Fraise, Fruit de la passion
Vert citronKiwi, Pomme verte, Citron
Soleil couchantMangue, 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 True

Cette 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.

Voir la question dans le sujet PDF, p. 3 (nouvel onglet)

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 resultat

On 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.

Voir la question dans le sujet PDF, p. 3 (nouvel onglet)

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.

Voir la question dans le sujet PDF, p. 3 (nouvel onglet)

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_proche

Le 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 None

La 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
  1. 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.

  2. 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.

Voir la question dans le sujet PDF, p. 3 (nouvel onglet)

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.

Voir la question dans le sujet PDF, p. 4 (nouvel onglet)
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éalisableFruits communsRôle
Tropical3Référence exclue
Tropical citron2Candidate
Vert citron0Candidate

Une recherche de maximum commence par définir les candidats admissibles et la règle d’égalité.

Revoir les notions de cet exercice

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.