Solution de Classement des indices d'un tableau - Sujet 40 - EP NSI 2025

Moyen Officiel
Python (3.14.0)

Énoncé du problème

EXERCICE 1 (10 points)

Écrire une fonction recherche_indices_classement qui prend en paramètres un entier elt et un tableau d’entiers tab représenté par une liste Python, et qui renvoie trois listes Python d’entiers :

  • la première liste contient les indices des valeurs du tableau tab strictement inférieures à elt ;
  • la deuxième liste contient les indices des valeurs du tableau tab égales à elt ;
  • la troisième liste contient les indices des valeurs du tableau tab strictement supérieures à elt.

Exemples :

>>> recherche_indices_classement(3, [1, 3, 4, 2, 4, 6, 3, 0])
([0, 3, 7], [1, 6], [2, 4, 5])
>>> recherche_indices_classement(3, [1, 4, 2, 4, 6, 0])
([0, 2, 5], [], [1, 3, 4])
>>>recherche_indices_classement(3, [1, 1, 1, 1])
([0, 1, 2, 3], [], [])
>>> recherche_indices_classement(3, [])
([], [], [])

EXERCICE 2 (10 points)

Une professeure de NSI décide de gérer les résultats de sa classe sous la forme d’un dictionnaire :

  • les clefs sont les noms des élèves ;
  • les valeurs sont des dictionnaires dont les clefs sont les types d’épreuves sous forme de chaîne de caractères et les valeurs sont les notes obtenues associées à leurs coefficients dans une liste.

Avec :

resultats = {
    'Dupont': {
        'DS1': [15.5, 4],
        'DM1': [14.5, 1],
        'DS2': [13, 4],
        'PROJET1': [16, 3],
        'DS3': [14, 4]
    },
    'Durand': {
        'DS1': [6 , 4],
        'DS2': [8, 4],
        'PROJET1': [9, 3],
        'IE1': [7, 2],
        'DS3': [12, 4]
    }
}

L’élève dont le nom est Durand a ainsi obtenu au DS2 la note de 8 avec un coefficient 4.

La professeure crée une fonction moyenne qui prend en paramètre le nom d’un de ses élèves et renvoie sa moyenne arrondie au dixième. Si l’élève n’a pas de notes, on considère que sa moyenne est nulle. Si le nom donné n’est pas dans les résultats, la fonction renvoie None.

Compléter le code de la professeure ci-dessous :

def moyenne(nom, resultats):
    '''Renvoie la moyenne de l'élève nom, selon le dictionnaire 
    resultats. Si nom n'est pas dans le dictionnaire, 
    la fonction renvoie None.'''
    if nom in ...: 
        notes = resultats[nom]
        if ...: # pas de notes 
            return 0
        total_points = ... 
        total_coefficients = ... 
        for ...  in notes.values(): 
            note, coefficient = valeurs
            total_points = total_points + ... * coefficient 
            ... = ... + coefficient 
        return round( ... / total_coefficients, 1 ) 
    else:
        return None

Exemples :

>>> moyenne("Dupont", resultats)
14.5
>>> moyenne("Durand", resultats)
8.5

Les contraintes ci-dessous sont ajoutées par la plateforme et ne font pas partie du sujet.

Exercice 1

Contraintes :

  • elt est un entier avec -10^9 <= elt <= 10^9
  • tab est une liste Python d’entiers avec 0 <= len(tab) <= 10^4
  • -10^9 <= tab[i] <= 10^9 pour tout indice i valide
  • tab peut être vide : dans ce cas les trois listes renvoyées sont vides
  • tab n’est pas nécessairement trié et peut contenir des valeurs répétées
  • la fonction renvoie un triplet de trois listes d’indices, chacune dans l’ordre croissant des indices

Exercice 2

Contraintes :

  • nom est une chaîne de caractères
  • resultats est un dictionnaire dont les clefs sont des chaînes de caractères (les noms des élèves) et les valeurs des dictionnaires, avec 0 <= len(resultats) <= 10^3
  • chaque dictionnaire d’élève associe un nom d’épreuve (chaîne de caractères) à une liste [note, coefficient] de longueur 2, avec au plus 10^2 épreuves par élève
  • note est un entier ou un flottant avec 0 <= note <= 20
  • coefficient est un entier avec 1 <= coefficient <= 10
  • si nom est une clef de resultats associée à un dictionnaire vide, la fonction renvoie 0
  • si nom n’est pas une clef de resultats, la fonction renvoie None
  • sinon la fonction renvoie la moyenne pondérée arrondie au dixième

Solution

Exercice 1 - classer les indices d’un tableau

L’idée. On ne cherche pas des valeurs, mais des positions. On parcourt donc le tableau une seule fois, en regardant chaque case avec son indice. Pour chaque indice, la valeur est soit strictement plus petite que elt, soit égale à elt, soit strictement plus grande : on range cet indice dans la liste correspondante. À la fin, on renvoie les trois listes d’un coup.

Un petit exemple. Avec elt = 3 et tab = [1, 3, 4] : l’indice 0 (valeur 1) part dans les inférieurs, l’indice 1 (valeur 3) dans les égaux, l’indice 2 (valeur 4) dans les supérieurs. On obtient ([0], [1], [2]).

def recherche_indices_classement(elt, tab):
    inferieurs = []
    egaux = []
    superieurs = []
    # On parcourt les indices, pas les valeurs : c'est l'indice que l'on range
    for i in range(len(tab)):
        if tab[i] < elt:
            inferieurs.append(i)
        elif tab[i] == elt:
            egaux.append(i)
        else:
            superieurs.append(i)
    return (inferieurs, egaux, superieurs)

Les trois listes commencent vides et se remplissent au fur et à mesure. La boucle for i in range(len(tab)) fournit les indices dans l’ordre croissant, donc chaque liste est automatiquement triée, sans travail supplémentaire. Comme les trois cas sont enchaînés par if / elif / else, chaque indice est rangé dans exactement une liste. Et si tab est vide, la boucle ne tourne pas une seule fois : on renvoie bien ([], [], []).

Exercice 2 - la moyenne d’un élève

L’idée. C’est une moyenne pondérée : on additionne toutes les notes multipliées par leur coefficient, puis on divise par la somme des coefficients. Le dictionnaire de l’élève donne, pour chaque épreuve, la liste [note, coefficient] ; il suffit donc de parcourir ses valeurs en faisant grandir deux totaux. Restent deux cas particuliers, traités avant le calcul : un nom absent du dictionnaire (on renvoie None) et un élève sans aucune note (on renvoie 0, car on ne pourrait pas diviser par une somme de coefficients nulle).

Un petit exemple. Pour Durand, total_points vaut 6*4 + 8*4 + 9*3 + 7*2 + 12*4 = 145 et total_coefficients vaut 4 + 4 + 3 + 2 + 4 = 17. La division donne 8.529..., soit 8.5 une fois arrondie au dixième.

def moyenne(nom, resultats):
    '''Renvoie la moyenne de l'élève nom, selon le dictionnaire
    resultats. Si nom n'est pas dans le dictionnaire,
    la fonction renvoie None.'''
    if nom in resultats:
        notes = resultats[nom]
        if len(notes) == 0: # pas de notes
            return 0
        total_points = 0
        total_coefficients = 0
        for valeurs in notes.values():
            note, coefficient = valeurs
            total_points = total_points + note * coefficient
            total_coefficients = total_coefficients + coefficient
        return round( total_points / total_coefficients, 1 )
    else:
        return None

total_points accumule les notes déjà multipliées par leur coefficient, total_coefficients la somme des coefficients rencontrés ; les deux partent de 0 et grandissent ensemble à chaque tour de boucle. La ligne note, coefficient = valeurs sépare la liste de deux éléments en deux variables plus faciles à lire. Le test len(notes) == 0 n’est pas un détail : sans lui, un élève sans épreuve provoquerait une division par zéro. Enfin, round(..., 1) réalise l’arrondi au dixième demandé par l’énoncé.