Épreuve pratique · 2026 · Sujet 4

Bac NSI pratique 2026 sujet 4 : Croissance des plantes et suppression dans une liste

Des agronomes mesurent chaque jour la hauteur des plantes, la température et l’humidité d’une serre. Chaque Plante possède nom, espece, croissance (durée moyenne en jours), taille (en cm) et exposition (ombre, mi-ombre ou plein soleil). Chaque mesure est un dictionnaire avec plante, jour, hauteur, temperature et humidite. L’objectif est de regrouper les mesures puis de retirer celles prises hors de l’intervalle 20 à 25°C, bornes incluses. Attention : croissance est une durée ; il ne faut pas calculer ici une vitesse en cm par jour.

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

Croissance des plantes et suppression dans une liste

Des agronomes mesurent chaque jour la hauteur des plantes, la température et l’humidité d’une serre. Chaque Plante possède nom, espece, croissance (durée moyenne en jours), taille (en cm) et exposition (ombre, mi-ombre ou plein soleil). Chaque mesure est un dictionnaire avec plante, jour, hauteur, temperature et humidite. L’objectif est de regrouper les mesures puis de retirer celles prises hors de l’intervalle 20 à 25°C, bornes incluses. Attention : croissance est une durée ; il ne faut pas calculer ici une vitesse en cm par jour.

NomDurée (jours)Taille (cm)Exposition
Basilic6040plein soleil
Tomate80100plein soleil
Menthe8050mi-ombre
Tournesol85200plein soleil
Fougère9080ombre

Le dossier comporte le sujet et les fichiers listés dans les téléchargements. Les programmes de départ et un aperçu des grands jeux de données sont présentés ci-dessous ; les fichiers complets sont téléchargeables. 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 : culture.py
#############################################################################
# Jeux de données fournis                                                   #
#############################################################################
from plantes import Plante, plantes
from mesures import mesures

#############################################################################
# Écrire le code de la fonction croissance_moyenne de la question 1         #
#############################################################################


def croissance_moyenne(plantes):
    pass


#############################################################################
# Écrire le code de la fonction dictionnaire_mesure de la question 2      #
#############################################################################

def dictionnaire_mesure(plantes, mesures):
    pass


#############################################################################
# Fonction défaillante à analyser et corriger pour les questions 3 et 4     #
#############################################################################

def purger_mesures_extremes(liste_mesures):
    """
    Supprime de la liste toutes les mesures dont la température 
    n'est pas comprise entre 20 et 25°C inclus.
    """
    for mesure in liste_mesures:
        if mesure['temperature'] < 20 or mesure['temperature'] > 25:
            liste_mesures.remove(mesure)


def test_purger():
    mesures_test = [
        {'jour': 1, 'plante': 'Basilic', 'temperature': 18.0},
        {'jour': 2, 'plante': 'Basilic', 'temperature': 19.0},
        {'jour': 3, 'plante': 'Basilic', 'temperature': 22.0},
        {'jour': 4, 'plante': 'Basilic', 'temperature': 28.0},
        {'jour': 5, 'plante': 'Basilic', 'temperature': 29.0}
    ]

    purger_mesures_extremes(mesures_test)

    print("Résultat après la purge :")
    for m in mesures_test:
        print(f"Jour {m['jour']} : {m['temperature']}°C")
Données fournies : mesures.py

Le fichier mesures.py contient la liste mesures et ses 305 enregistrements. Voici les trois premiers, dans l’ordre du fichier.

jourplantehauteurtemperaturehumidite
1Basilic0.8529.350.89
1Tomate1.2721.5147.19
1Menthe0.6727.7561.14

Pour exécuter le programme sur toutes les données et retrouver les résultats du sujet, utilisez le fichier intégral fourni. Il est aussi inclus dans l’archive ZIP de cette page.

Télécharger mesures.py complet

Code fourni : plantes.py
class Plante:
    def __init__(self, nom, espece, croissance, taille, exposition):
        self.nom = nom
        self.espece = espece
        self.croissance = croissance  # en jours
        self.taille = taille          # en cm
        self.exposition = exposition  # type d'exposition


plantes = [
    Plante("Basilic", "Ocimum basilicum", 60, 40, "plein soleil"),
    Plante("Tomate", "Solanum lycopersicum", 80, 100, "plein soleil"),
    Plante("Menthe", "Mentha spicata", 80, 50, "mi-ombre"),
    Plante("Tournesol", "Helianthus annuus", 85, 200, "plein soleil"),
    Plante("Fougère", "Dryopteris filix-mas", 90, 80, "ombre")
]

Question 1

#

Écrire croissance_moyenne(plantes) qui renvoie la moyenne des durées de croissance, ou None si la liste est vide. Écrire au moins deux tests, dont celui de la liste vide.

Indice

Accéder à un attribut avec un point.

Comprendre la correction
def croissance_moyenne(plantes):
    if not plantes:
        return None
    total = 0
    for plante in plantes:
        total += plante.croissance
    return total / len(plantes)

On additionne l’attribut croissance de chaque instance. Pour les cinq plantes fournies, (60+80+80+85+90)/5=79 jours. Le contrôle initial empêche la division par zéro.

assert croissance_moyenne([]) is None
assert croissance_moyenne([Plante('A','x',10,20,'ombre'),
                          Plante('B','x',30,40,'ombre')]) == 20.0
assert croissance_moyenne(plantes) == 79.0
Voir la question dans le sujet PDF, p. 3 (nouvel onglet)

Question 2

#

Écrire dictionnaire_mesure(plantes, mesures) : chaque clé est le nom d’une plante présente dans plantes, et chaque valeur la liste de ses mesures. Une plante sans mesure doit avoir une liste vide. Concevoir une série de tests pertinente.

PythonUne liste indépendante pour chaque planteÉcrivez votre solution et mettez-la à l’épreuve

Écrivez dictionnaire_mesure(plantes, mesures). Les clés sont tous les noms des objets Plante fournis, même sans relevé. Chaque valeur contient les dictionnaires de mesure complets, dans leur ordre initial. Une mesure d’un nom absent de plantes est ignorée.

def dictionnaire_mesure(plantes, mesures):
    # À vous de jouer
    pass

Les cas de test proposés :

  • Une plante sans relevé : La présence d’une plante ne dépend pas de ses mesures.
  • Plusieurs relevés et ordre : Regrouper ne signifie pas trier par jour.
  • Listes indépendantes : Deux clés ne doivent pas partager une même liste mutable.
  • Nom inconnu : Les clés attendues proviennent du catalogue de plantes.
  • Aucune plante : Une collection vide conduit à un dictionnaire vide.
Indice

Les plantes sans relevé doivent exister avant le parcours des mesures.

Comprendre la correction
def dictionnaire_mesure(plantes, mesures):
    resultat = {plante.nom: [] for plante in plantes}
    for mesure in mesures:
        nom = mesure['plante']
        if nom in resultat:
            resultat[nom].append(mesure)
    return resultat

On crée d’abord toutes les clés, avec une liste distincte pour chacune. Ensuite on distribue les mesures. La garde nom in resultat ignore un éventuel nom inconnu, puisque les clés attendues viennent de plantes. Ne pas utiliser dict.fromkeys(noms, []) : toutes les clés partageraient la même liste.

a=Plante('A','x',10,20,'ombre'); b=Plante('B','x',30,40,'ombre')
m1={'plante':'A','jour':1}; m2={'plante':'A','jour':2}
assert dictionnaire_mesure([a,b],[m1,m2]) == {'A':[m1,m2],'B':[]}
assert dictionnaire_mesure([a,b],[]) == {'A':[],'B':[]}
assert dictionnaire_mesure([],[]) == {}

Imaginons deux plantes A et B, puis deux relevés pour A. Au départ, le dictionnaire est {'A': [], 'B': []}. Après le premier relevé, seule la liste associée à A contient une mesure ; après le second, elle en contient deux, tandis que B reste présente avec une liste vide. Le point essentiel est l’indépendance des listes. Un test utile consiste à ajouter une mesure au groupe A puis à vérifier que B n’a pas changé. Cela détecte un partage involontaire de la même liste entre toutes les clés.

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

Question 3

#

Exécuter test_purger et analyser purger_mesures_extremes pour identifier l’erreur logique : des températures extrêmes restent après la suppression.

Indice

Suivre simultanément la position courante et le déplacement des cases.

Comprendre la correction

La boucle for avance son indice interne pendant que remove décale les éléments. Avec 18,19,22,28,29, supprimer 18 fait passer 19 à l’indice 0 ; la boucle visite ensuite l’indice 1, donc 22. Elle supprime 28 et saute de la même manière 29. Le résultat fautif est 19,22,29 au lieu de 22. Une suppression peut donc faire sauter l’élément suivant.

Pourquoi une température survit-elle ?Un 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. Après suppression de 18 dans [18,19,22], quelle valeur passe à l’indice 0 ?

    19. Les éléments se décalent à gauche.

  2. Que conserve la règle climatique ?

    20 et 25. Les deux bornes sont autorisées.

Appuyez votre explication sur les valeurs et les conditions exactes du programme.

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

Question 4

#

Proposer une version corrigée de purger_mesures_extremes qui retire toutes les mesures à température strictement inférieure à 20°C ou strictement supérieure à 25°C.

PythonSupprimer sans sauter la mesure suivanteÉcrivez votre solution et mettez-la à l’épreuve

Corrigez purger_mesures_extremes(liste_mesures). Retirez de la liste reçue les mesures dont temperature est strictement inférieure à 20 ou strictement supérieure à 25. Modifiez cette même liste et conservez l’ordre des mesures restantes ; la fonction ne doit pas renvoyer une liste de remplacement.

def purger_mesures_extremes(liste_mesures):
    # À vous de jouer
    pass

Les cas de test proposés :

  • Deux suppressions consécutives : Le parcours défaillant saute 19 puis 29 après les décalages.
  • Les deux bornes sont autorisées : La plage de conservation est fermée aux deux extrémités.
  • Tout supprimer : Aucune mesure extrême ne doit survivre.
  • Un alias doit voir la purge : Une réaffectation locale ne modifie pas la liste de l’appelant.
  • Conserver les données complètes : La purge retire des mesures ; elle ne reconstruit pas des dictionnaires amputés.
  • Liste vide : Aucune suppression ni accès hors limites ne doit être tenté.
Comprendre la correction
def purger_mesures_extremes(liste_mesures):
    for i in range(len(liste_mesures) - 1, -1, -1):
        if not 20 <= liste_mesures[i]['temperature'] <= 25:
            liste_mesures.pop(i)

Le parcours part de la fin. Supprimer une case ne change alors que les indices déjà visités ; les positions restant à examiner sont intactes. La fonction modifie bien la liste fournie, comme le code initial et son appel le prévoient. Une autre solution correcte est une affectation de tranche liste_mesures[:] = [m for m in liste_mesures if 20<=m["temperature"]<=25] ; une simple réaffectation locale n’aurait pas cet effet sur la liste appelante.

for valeurs, attendu in [([],[]),([18,19,22,28,29],[22]),
                         ([20,25],[20,25]),([18,19],[])]:
    mesures_test=[{'temperature': t} for t in valeurs]
    alias=mesures_test
    purger_mesures_extremes(mesures_test)
    assert alias is mesures_test
    assert [m['temperature'] for m in alias] == attendu

Pourquoi le parcours inverse est-il sûr ? À l’indice i, les cases à droite ont déjà été traitées. Supprimer i décale ces cases déjà traitées, mais ne change pas les indices strictement inférieurs à i. L’itération suivante peut donc examiner i−1 sans perdre de mesure. À l’inverse, dans un parcours croissant, l’élément i+1 devient i après la suppression ; avancer ensuite à i+1 le saute. Cette explication reste vraie pour deux, trois ou dix températures extrêmes consécutives, au-delà du seul exemple testé.

Voir la question dans le sujet PDF, p. 4 (nouvel onglet)
Suivre une purge correcte ou défaillanteUn atelier pour expérimenter

Choisissez une série et une stratégie. Chaque ligne montre la température examinée et la liste restante ; comparez les valeurs qui sont sautées.

Lire le résultat de l’expérience initiale

Valeurs conservées : 22.

Un parcours à rebours ne saute aucune case encore à examiner.

Indice examinéTempératureAprès traitement
42918, 19, 22, 28
32818, 19, 22
22218, 19, 22
11918, 22
01822

Changer une liste pendant son parcours demande une stratégie qui préserve les indices à visiter.

Revoir les notions de cet exercice

Du sujet à la méthode

Votre prochaine séance de révision

  • Vérifier si une fonction doit renvoyer une nouvelle liste ou modifier la liste existante.
  • Les températures exactement 20 et 25 sont des tests indispensables.

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_4 (PDF). Corrigé et explications pédagogiques proposés par Sofien.