Solution de Minimum et maximum d'un tableau - Sujet 20 - EP NSI 2025
Énoncé du problème
Exercice 1
EXERCICE 1 (10 points)
Écrire une fonction min_et_max qui prend en paramètre un tableau de nombres tab non vide, et qui renvoie la plus petite et la plus grande valeur du tableau sous la forme d’un dictionnaire à deux clés min et max.
Les tableaux seront représentés sous forme de liste Python.
L’utilisation des fonctions natives min, max et sorted, ainsi que la méthode sort n’est pas autorisée.
Exemples :
>>> min_et_max([0, 1, 4, 2, -2, 9, 3, 1, 7, 1])
{'min': -2, 'max': 9}
>>> min_et_max([0, 1, 2, 3])
{'min': 0, 'max': 3}
>>> min_et_max([3])
{'min': 3, 'max': 3}
>>> min_et_max([1, 3, 2, 1, 3])
{'min': 1, 'max': 3}
>>> min_et_max([-1, -1, -1, -1, -1])
{'min': -1, 'max': -1}
Exercice 2
EXERCICE 2 (10 points)
On dispose d’une classe Carte permettant de créer des objets modélisant des cartes à jouer.
Compléter la classe Paquet_de_cartes suivante en respectant les spécifications données dans les chaînes de documentation.
Ajouter une assertion dans la méthode recuperer_carte de la classe Paquet_de_cartes afin de vérifier que le paramètre pos est correct.
On rappelle que l’instruction
assert condition, message
permet de vérifier que la condition est vraie. Si ce n’est pas le cas, le programme s’arrête et affiche le message d’erreur fourni.
class Carte:
def __init__(self, c, v):
"""Initialise les attributs couleur (entre 1 et 4),
et valeur (entre 1 et 13). """
self.couleur = c
self.valeur = v
def recuperer_valeur(self):
""" Renvoie la valeur de la carte :
As, 2, ..., 10, Valet, Dame, Roi """
valeurs = ['As','2', '3', '4', '5', '6', '7', '8',
'9', '10', 'Valet', 'Dame', 'Roi']
return valeurs[self.valeur - 1]
def recuperer_couleur(self):
""" Renvoie la couleur de la carte
(parmi pique, coeur, carreau, trèfle). """
couleurs = ['pique', 'coeur', 'carreau', 'trèfle']
return couleurs[self.couleur - 1]
class Paquet_de_cartes:
def __init__(self):
""" Initialise l'attribut contenu avec une liste des 52
objets Carte possibles rangés par valeurs croissantes en
commençant par pique, puis cœur, carreau et trèfle. """
...
...
...
...
def recuperer_carte(self, pos):
""" Renvoie la carte qui se trouve à la position pos
(entier compris entre 0 et 51). """
...
...
Exemple :
>>> jeu = Paquet_de_cartes()
>>> carte1 = jeu.recuperer_carte(20)
>>> carte1.recuperer_valeur() \
+ " de " + carte1.recuperer_couleur()
"8 de coeur"
>>> carte2 = jeu.recuperer_carte(0)
>>> carte2.recuperer_valeur() \
+ " de " + carte2.recuperer_couleur()
"As de pique"
>>> carte3 = jeu.recuperer_carte(52)
AssertionError : paramètre pos invalide
Les contraintes ci-dessous sont ajoutées par la plateforme et ne font pas partie du sujet.
Exercice 1
Contraintes :
tabest une liste Python non vide :1 <= len(tab) <= 10^4tab[i]est un entier avec-10^9 <= tab[i] <= 10^9tabn’est pas nécessairement trié et peut contenir des doublons ou des valeurs toutes égalesmin_et_maxrenvoie un dictionnaire à exactement deux clés,minetmaxmin,max,sortedet la méthodesortne doivent pas être utilisés
Exercice 2
Contraintes :
Paquet_de_cartes()s’appelle sans argument et initialise l’attributcontenuavec exactement 52 objetsCarte- pour chaque
Carte,couleurest un entier de 1 à 4 etvaleurun entier de 1 à 13 - l’ordre du paquet est : pique, puis cœur, puis carreau, puis trèfle, et à l’intérieur de chaque couleur les valeurs sont croissantes
posest un entier ; un appel valide vérifie0 <= pos <= 51- tout appel de
recuperer_carteavec unposentier hors de l’intervalle[0, 51]doit lever uneAssertionError recuperer_carterenvoie un objetCarte, pas une chaîne de caractères
Solution
Solution - Sujet 20 (EP NSI 2025)
Exercice 1 - minimum et maximum d’un tableau
L’idée. On n’a pas le droit d’utiliser min, max ni un tri : il faut donc parcourir le tableau nous-mêmes. On retient deux valeurs au fur et à mesure : le plus petit nombre vu jusqu’ici et le plus grand. À chaque nouvelle valeur, on se demande si elle bat le record du bas ou le record du haut, et si oui on met le record à jour. À la fin du parcours, ces deux valeurs sont bien le minimum et le maximum de tout le tableau.
Le point important est le départ : on initialise les deux records avec tab[0], la première valeur du tableau. C’est autorisé parce que l’énoncé garantit que le tableau n’est pas vide.
Un petit exemple. Pour [3, 1, 4] : on part de minimum = 3 et maximum = 3. Avec 1, le minimum devient 1. Avec 4, le maximum devient 4. On renvoie donc {'min': 1, 'max': 4}.
def min_et_max(tab):
minimum = tab[0]
maximum = tab[0]
# Le tableau est non vide : on peut partir de tab[0], qui est à la fois
# le plus petit et le plus grand de toutes les valeurs vues pour l'instant
for valeur in tab:
if valeur < minimum:
minimum = valeur
if valeur > maximum:
maximum = valeur
return {'min': minimum, 'max': maximum}
Explications. minimum et maximum contiennent, à tout moment de la boucle, le plus petit et le plus grand des nombres déjà examinés. Les deux if sont indépendants (ce n’est pas un if / else) : une même valeur peut battre les deux records en même temps, ce qui arrive par exemple au tout premier tour. Repasser sur tab[0] dans la boucle ne pose aucun problème : les deux tests sont faux, rien ne change. Enfin, on renvoie bien un dictionnaire à deux clés 'min' et 'max', pas deux valeurs séparées.
Sur [-1, -1, -1, -1, -1], aucun test n’est jamais vrai et on renvoie {'min': -1, 'max': -1}, ce qui est correct.
Exercice 2 - le paquet de 52 cartes
L’idée. Une carte est décrite par deux nombres : une couleur de 1 à 4 (pique, coeur, carreau, trèfle) et une valeur de 1 à 13 (As jusqu’au Roi). Construire le paquet complet, c’est donc fabriquer toutes les combinaisons possibles : pour chaque couleur, les treize valeurs dans l’ordre croissant. Deux boucles imbriquées suffisent : la boucle extérieure sur les couleurs, la boucle intérieure sur les valeurs. On obtient 4 x 13 = 52 cartes, rangées exactement dans l’ordre demandé.
Pour recuperer_carte, il n’y a rien à calculer : les cartes sont déjà dans le bon ordre dans la liste contenu, donc la carte numéro pos est simplement self.contenu[pos]. Avant de la renvoyer, on vérifie avec un assert que pos est bien compris entre 0 et 51.
Un petit exemple. La 21e carte du paquet est à la position 20. Les positions 0 à 12 sont les piques, donc la position 20 tombe dans le deuxième bloc, celui des coeurs, à la 8e place de ce bloc : c’est le “8 de coeur”, ce que confirme l’énoncé.
class Paquet_de_cartes:
def __init__(self):
""" Initialise l'attribut contenu avec une liste des 52
objets Carte possibles rangés par valeurs croissantes en
commençant par pique, puis cœur, carreau et trèfle. """
self.contenu = []
# Couleur par couleur, puis valeur par valeur : cet ordre des deux
# boucles est ce qui range le paquet pique, coeur, carreau, trèfle
for couleur in range(1, 5):
for valeur in range(1, 14):
self.contenu.append(Carte(couleur, valeur))
def recuperer_carte(self, pos):
""" Renvoie la carte qui se trouve à la position pos
(entier compris entre 0 et 51). """
assert 0 <= pos <= 51, "paramètre pos invalide"
return self.contenu[pos]
Explications. self.contenu est un attribut : une liste rangée dans l’objet, que les autres méthodes retrouveront avec self.contenu. range(1, 5) donne 1, 2, 3, 4 et range(1, 14) donne 1 à 13 : ce sont bien les numéros attendus par la classe Carte, qui fait ses - 1 toute seule au moment de lire ses listes couleurs et valeurs. Attention à ne pas écrire range(4) et range(13), qui commenceraient à 0 et décaleraient tout le paquet.
L’ordre des deux boucles est ce qui décide du rangement : comme la couleur est à l’extérieur, on pose d’abord les treize piques, puis les treize coeurs, et ainsi de suite. Si on échangeait les deux boucles, on obtiendrait As de pique, As de coeur, As de carreau… et l’exemple de l’énoncé ne fonctionnerait plus.
Enfin, assert 0 <= pos <= 51, "paramètre pos invalide" arrête le programme avec une AssertionError quand la position demandée n’existe pas, comme pour recuperer_carte(52). Sans cette ligne, pos = 52 provoquerait une erreur d’indice moins parlante, et pos = -1 renverrait silencieusement la dernière carte du paquet.
recuperer_carte renvoie l’objet Carte lui-même, pas une chaîne de caractères : c’est ensuite l’utilisateur qui appelle recuperer_valeur() et recuperer_couleur() dessus, comme dans l’exemple du sujet.