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é.
Exercice 1 · 6 points
Peut-on décider si un programme s’arrête ?
Les triples guillemets Python permettent de représenter un programme par une chaîne sur plusieurs lignes. On définit :
programme1 = """
x = 10
y = 10
while x > 0:
x = x - 1
y = y + 1
"""
programme2 = """
def boucle_infinie():
while True:
pass # Ne rien faire
boucle_infinie()
"""La fonction Python exec exécute le texte passé en paramètre. Ainsi, exec("r = 42") donne ensuite r == 42 ; après exec(programme1), x + y vaut 20. L’appel exec(programme2) ne termine pas.
Question 1
#On suppose que l’on exécute le programme contenu dans programme1. Donner les valeurs de x et y après exécution.
Comprendre la correction
x = 0 et y = 20. La boucle s’exécute dix fois : à chaque tour, x perd 1 et y gagne 1. L’invariant x + y = 20 est conservé et la condition devient fausse pour x nul.
Question 2
#Expliquer pourquoi tout programme Python peut être vu comme une chaîne de caractères.
Comprendre la correction
Le code source d’un programme est une suite finie de caractères : lettres, chiffres, espaces, retours à la ligne et symboles. Cette suite peut donc être stockée dans une chaîne. Il faut conserver ses retours à la ligne et son indentation pour préserver le sens du programme.
programme3 = """
x = 10
while x != 0:
x = x - 2
"""programme4 = """
x = 10
while x > 0:
x = x + 2
"""programme5 = """
x = 10
while x < 0:
x = x + 4
"""programme6 = """
x = 10
while x != 0:
x = x - 4
"""Question 3
#On exécute programme3, programme4, programme5 et programme6 avec exec. Déterminer lesquels terminent et lesquels ne terminent pas.
Indice
Pour programme 6, regardez la valeur après2 puis après3 tours.
Comprendre la correction
| Programme | Termine ? | Raison |
|---|---|---|
| 3 | Oui | 10, 8, 6, 4, 2, 0 : cinq tours, puis x == 0. |
| 4 | Non | x reste positif et augmente de 2 à chaque tour. |
| 5 | Oui | La condition 10 < 0 est fausse dès le départ : aucun tour. |
| 6 | Non | x = 10 - 4 k ; aucun entier k ne donne 0. La suite passe de 2 à -2. |
Une variable qui décroît n’assure pas à elle seule l’arrêt : la condition doit devenir fausse. Dans le programme 6, on teste l’égalité à 0 et non le signe de x.
def arret_essai1(programme):
exec(programme)
return TrueQuestion 4
#Indiquer ce que réalise le programme suivant et s’il permet de répondre au problème posé : construire arret(programme), qui renvoie True si le programme termine et False sinon, tout en s’arrêtant elle-même dans tous les cas.
Comprendre la correction
arret_essai1 exécute le programme puis renvoie True si l’exécution arrive à son terme. Si le programme boucle indéfiniment, la fonction reste bloquée dans exec et ne renvoie jamais False. Elle ne décide donc pas le problème de l’arrêt.
Attendre plus longtemps ou ajouter une limite de temps ne résout pas le problème : un programme peut finir après cette limite.
Question 5
#Expliquer succinctement le principe de l’algorithme de Boyer-Moore qui permet d’implémenter recherche(mot, texte), renvoyant si le mot est présent dans le texte.
Comprendre la correction
On aligne le motif sur une portion du texte et on compare ses caractères en partant de la droite. À la première différence, des informations pré-calculées sur le motif permettent de décaler cet alignement de plusieurs positions sans perdre d’occurrence possible. Si tous les caractères correspondent, une occurrence est trouvée.
Dans la variante du « mauvais caractère » étudiée en NSI, le caractère du texte responsable de l’échec sert à choisir un décalage cohérent avec ses positions dans le motif.
Question 6
#Écrire arret_essai2(programme), qui renvoie True si la chaîne "while" n’est pas utilisée dans le programme, et False sinon.
Comprendre la correction
def arret_essai2(programme):
return not recherche("while", programme)recherche renvoie déjà un booléen ; not inverse sa valeur. Ce test porte sur du texte brut, même si « while » apparaît dans une chaîne ou un commentaire.
Question 7
#Montrer que arret_essai2 peut renvoyer True alors que le programme ne s’arrête pas, et False alors qu’il s’arrête. Il n’y a pas que les boucles while qui peuvent poser des problèmes de non-terminaison.
Indice 1
Une boucle for peut parcourir un itérateur sans fin.
Indice 2
Une condition fausse dès le départ suffit à une boucle while pour terminer.
Comprendre la correction
for element in iter(int, 1):
passCe premier contre-exemple ne contient pas « while ». L’itérateur appelle int(), qui renvoie toujours 0, jusqu’à rencontrer 1 : cela n’arrive jamais. Le test textuel renvoie donc True alors que la boucle ne termine pas.
while False:
passLe second texte contient « while », mais la boucle n’effectue aucun tour : le programme termine. Une fonction qui s’appelle récursivement sans fin illustre aussi l’idée dans un modèle théorique, mais en Python concret elle finit généralement par lever RecursionError ; le premier contre-exemple évite cette confusion.
Question 8
#En supposant l’existence de arret, écrire terminaison_inverse(programme), qui termine si le programme ne termine pas et ne termine pas s’il termine. On pourra utiliser boucle_infinie.
Indice
Inversez le comportement annoncé par le décideur supposé.
Comprendre la correction
def terminaison_inverse(programme):
if arret(programme):
boucle_infinie()Si arret annonce une terminaison, on lance une boucle infinie. Sinon, le corps conditionnel est ignoré et la fonction atteint sa fin. L’existence de arret est ici une hypothèse pour raisonner, pas une fonction disponible en Python.
programme_paradoxal = "terminaison_inverse(programme_paradoxal)"Question 9
#Étudier si exec(programme_paradoxal) termine ou non, avec programme_paradoxal = "terminaison_inverse(programme_paradoxal)".
Indice
Étudiez successivement les deux réponses possibles du décideur.
Comprendre la correction
Supposons que ce programme termine. Alors arret(programme_paradoxal) est vrai, donc terminaison_inverse boucle indéfiniment : contradiction.
Supposons maintenant qu’il ne termine pas. arret renvoie alors faux, donc terminaison_inverse atteint sa fin : nouvelle contradiction. Les deux réponses possibles contredisent le comportement exigé ; l’hypothèse d’un décideur universel est impossible.
Question 10
#Indiquer ce que l’on peut conclure sur la fonction arret.
Comprendre la correction
Il n’existe pas de fonction calculable qui, pour tout programme, termine toujours et répond correctement s’il termine. Le problème de l’arrêt est indécidable. Cela n’interdit pas de prouver la terminaison de programmes particuliers, comme les programmes 1 ou 3.
Question 11
#Expliquer si l’impossibilité d’écrire une telle fonction arret est due aux limitations du langage Python.
Comprendre la correction
Non. La contradiction utilise la capacité à représenter un programme comme une donnée, à effectuer un test et à boucler. Elle concerne le calcul algorithmique général, pas une faiblesse de la syntaxe de Python. Changer de langage universel ou accélérer la machine ne supprime pas cette impossibilité.
Une suite décroissante finit-elle toujours ?Un atelier pour expérimenter
Choisissez l’un des quatre programmes et le nombre d’itérations observées. Comparez la valeur calculée à la condition de boucle. Une simulation finie observe un préfixe ; la preuve explique la suite entière.
Lire le résultat de l’expérience initiale
Après 5 tour(s), x = -10 : la condition reste vraie
x vaut toujours 10 - 4k, donc est congru à 2 modulo 4 : il ne peut pas être nul.
| Tour | x | Condition |
|---|---|---|
| 0 | 10 | Vraie |
| 1 | 6 | Vraie |
| 2 | 2 | Vraie |
| 3 | -2 | Vraie |
| 4 | -6 | Vraie |
| 5 | -10 | Vraie |
Observer mille tours ne démontre pas une boucle infinie. Un invariant ou une formule permet ici de prouver ce qu’aucune attente finie ne peut décider en général.
Revoir les notions de cet exercice
Exercice 2 · 6 points
Compresser SIX ANANAS avec Huffman
Pour transmettre sur un canal non bruité, on cherche à réduire la taille de l’information. Le codage de Huffman, proposé en 1952, est un code de longueur variable optimal dans le cadre des codes préfixes binaires symbole par symbole pour des fréquences données. Le sujet annonce des réductions de taille de 20 % à 90 % ; nous vérifierons ce calcul sur son exemple, sans en faire une garantie universelle.
Partie A : coder du texte
La figure 1 donne ISO/CEI 8859-1, appelé Latin-1 dans le sujet. Chaque caractère y occupe 8 bits, soit deux chiffres hexadécimaux : la ligne puis la colonne. « H », ligne 4 x et colonne x8, a pour code 48. « Hello_World_! » donne 48 65 6C 6C 6F 5F 57 6F 72 6C 64 5F 21. SP représente l’espace.
Table Latin-1 complète de la figure 1
| Ligne | x0 | x1 | x2 | x3 | x4 | x5 | x6 | x7 | x8 | x9 | xA | xB | xC | xD | xE | xF |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0x | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure |
| 1x | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure |
| 2x | SP | ! | " | # | $ | % | & | ' | ( | ) | * | + | , | - | . | / |
| 3x | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | : | ; | < | = | > | ? |
| 4x | @ | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O |
| 5x | P | Q | R | S | T | U | V | W | X | Y | Z | [ | \ | ] | ^ | _ |
| 6x | ` | a | b | c | d | e | f | g | h | i | j | k | l | m | n | o |
| 7x | p | q | r | s | t | u | v | w | x | y | z | { | | | } | ~ | Position non utilisée dans la figure |
| 8x | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure |
| 9x | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure | Position non utilisée dans la figure |
| Ax | NBSP | ¡ | ¢ | £ | ¤ | ¥ | ¦ | § | ¨ | © | ª | « | ¬ | Tiret conditionnel | ® | ¯ |
| Bx | ° | ± | ² | ³ | ´ | µ | ¶ | · | ¸ | ¹ | º | » | ¼ | ½ | ¾ | ¿ |
| Cx | À | Á | Â | Ã | Ä | Å | Æ | Ç | È | É | Ê | Ë | Ì | Í | Î | Ï |
| Dx | Ð | Ñ | Ò | Ó | Ô | Õ | Ö | × | Ø | Ù | Ú | Û | Ü | Ý | Þ | ß |
| Ex | à | á | â | ã | ä | å | æ | ç | è | é | ê | ë | ì | í | î | ï |
| Fx | ð | ñ | ò | ó | ô | õ | ö | ÷ | ø | ù | ú | û | ü | ý | þ | ÿ |
txt = "SIX ANANAS"Question 1
#Calculer la taille en octets du texte contenu dans txt, puis la taille en bits nécessaire pour le stocker.
Comprendre la correction
Il y a 10 caractères, espace compris. Le texte occupe donc 10 octets = 80 bits. Ne pas compter seulement les lettres : l’espace est un symbole codé lui aussi.
Question 2
#Donner le codage de la chaîne txt.
Comprendre la correction
53 49 58 20 41 4E 41 4E 41 53On lit chaque caractère dans l’ordre : S, I, X, espace, A, N, A, N, A, S. La répétition d’un caractère répète son code fixe ; A vaut 41 et N vaut 4E.
Partie B : compression de Huffman
Le nombre d’occurrences d’un symbole est son nombre d’apparitions. Pour « DEECDDEBFACCECCEDBAEE », le sujet donne :
| Symbole | A | B | C | D | E | F |
|---|---|---|---|---|---|---|
| Occurrences | 2 | 2 | 5 | 4 | 7 | 1 |
Ce tableau se représente par le dictionnaire {'D': 4, 'E': 7, 'C': 5, 'B': 2, 'F': 1, 'A': 2}.
Question 3
#Écrire le tableau d’occurrences associé à txt.
Comprendre la correction
| Symbole | S | I | X | SP | A | N |
|---|---|---|---|---|---|---|
| Occurrences | 2 | 1 | 1 | 1 | 3 | 2 |
Un tableau peut présenter les symboles dans un autre ordre sans changer le résultat. Le total vaut 10.
Question 4
#Préciser à quoi correspond la somme des nombres d’occurrences.
Comprendre la correction
Elle est égale au nombre total de symboles du texte, donc à sa longueur : chaque position contribue exactement une fois à l’effectif du caractère qu’elle contient. Pour txt, elle vaut 10.
def occurrence(texte):
dico = {}
for lettre in ...:
if lettre in ...:
dico[lettre] = dico[lettre] + 1
else:
...
return ...Question 5
#Compléter occurrence(texte), qui renvoie le dictionnaire des occurrences.
Comprendre la correction
def occurrence(texte):
dico = {}
for lettre in texte:
if lettre in dico:
dico[lettre] = dico[lettre] + 1
else:
dico[lettre] = 1
return dicoUn symbole déjà rencontré voit son compteur augmenter de 1 ; un nouveau symbole est initialisé à 1 puisqu’on vient de le lire. Le dictionnaire vide est la bonne réponse pour un texte vide. Le retour vient après le parcours complet.
Une forêt contient au départ une feuille par symbole, pondérée par son effectif. On extrait les deux arbres de plus petite fréquence, on les greffe sous une nouvelle racine de poids égal à leur somme, puis on réinsère ce nouvel arbre. Les plus petits poids sont donc les plus prioritaires. À égalité, une nouvelle insertion passe avant les arbres de même priorité déjà présents. On recommence jusqu’à un seul arbre. Les arêtes gauches valent 0 et les droites 1.
La figure 2 montre les fusions de l’exemple à 21 symboles :
| Étape | Fusion | Forêt après insertion, poids croissants |
|---|---|---|
| 0 | Aucune | F1, A2, B2, D4, C5, E7 |
| 1 | F1 + A2 → 3 | B2, (F, A)3, D4, C5, E7 |
| 2 | B2 + 3 → 5 | D4, (B,(F, A))5, C5, E7 |
| 3 | D4 + 5 → 9 | C5, E7, 9 |
| 4 | C5 + E7 → 12 | 9, 12 |
| 5 | 9 + 12 → 21 | 21 |
| 6 | Étiqueter les arêtes par 0 et 1 | Arbre ci-dessous |
Lire les connexions du schéma
- 21 relié à 9 : 0
- 21 relié à 12 : 1
- 9 relié à D:4 : 0
- 9 relié à 5 : 1
- 5 relié à B:2 : 0
- 5 relié à 3 : 1
- 3 relié à F:1 : 0
- 3 relié à A:2 : 1
- 12 relié à C:5 : 0
- 12 relié à E:7 : 1
Question 6
#Construire l’arbre de Huffman associé à txt.
Indice
À chaque fusion, reprenez les deux plus petits poids de la forêt actuelle.
Comprendre la correction
| Fusion | Deux poids minimaux | Nouveau poids |
|---|---|---|
| 1 | I:1 et X:1 | 2 |
| 2 | SP:1 et (I, X):2 | 3 |
| 3 | S:2 et N:2 | 4 |
| 4 | (SP, I, X):3 et A:3 | 6 |
| 5 | (S, N):4 et (SP, I, X, A):6 | 10 |
Lire les connexions du schéma
- 10 relié à 4 : 0
- 10 relié à 6 : 1
- 4 relié à S:2 : 0
- 4 relié à N:2 : 1
- 6 relié à 3 : 0
- 6 relié à A:3 : 1
- 3 relié à SP:1 : 0
- 3 relié à 2 : 1
- 2 relié à I:1 : 0
- 2 relié à X:1 : 1
On fixe ici l’ordre initial des égalités à I, X, SP, S, N, A, par poids croissant. À poids égal, un nouvel arbre est inséré avant les arbres déjà présents, comme l’impose la règle du sujet. Le choix initial entre symboles de même effectif peut produire d’autres arbres corrects : les codes ne sont pas uniques.
Question 7
#Préciser à quoi correspond le poids de la racine de cet arbre.
Comprendre la correction
Le poids de la racine vaut 10, la somme des occurrences de tous les symboles, donc la longueur du texte. Chaque greffe conserve le poids total de la forêt : les deux poids retirés sont remplacés par leur somme.
Le code d’un symbole est la suite de bits du chemin racine-feuille. Dans l’exemple de la figure 2, F se code 0110 et E se code 11.
Question 8
#Indiquer le type de parcours à utiliser pour réaliser la table de codage à partir de l’arbre de Huffman.
Comprendre la correction
Un parcours en profondeur convient, par exemple préfixe, en transportant le chemin depuis la racine. On ajoute 0 en descendant à gauche et 1 à droite ; lorsqu’on atteint une feuille, la chaîne accumulée est le code de son symbole. Le point essentiel est de conserver le chemin, pas seulement de lister les feuilles.
Question 9
#Donner la table de codage pour txt.
Comprendre la correction
| Symbole | S | N | SP | I | X | A |
|---|---|---|---|---|---|---|
| Code | 00 | 01 | 100 | 1010 | 1011 | 11 |
Cette table correspond exactement à notre arbre de la question 6. Un autre arbre valide peut permuter certains bits : il faut surtout assurer la cohérence entre arbre, table et texte codé.
Question 10
#Justifier que le code de Huffman est un code de longueur variable.
Comprendre la correction
Les feuilles n’ont pas toutes la même profondeur : ici S, N et A ont des codes de 2 bits, l’espace de 3 bits, I et X de 4 bits. Les caractères fréquents reçoivent globalement les chemins courts. La propriété de préfixe, aucun code complet n’étant le début d’un autre, permet de les concaténer sans séparateur.
Question 11
#Coder txt à l’aide du code de Huffman et de l’arbre construit à la question 6.
Comprendre la correction
00 | 1010 | 1011 | 100 | 11 | 01 | 11 | 01 | 11 | 000010101011100110111011100Les barres de la première ligne sont des repères de correction : elles ne sont pas stockées. La concaténation finale contient 25 bits.
Question 12
#En reprenant le résultat de la partie A, déduire le taux de compression en pourcentage pour txt et vérifier la réduction annoncée entre 20 % et 90 %. Le taux est (encombrement initial - encombrement final) / encombrement initial.
Comprendre la correction
Le taux vaut (80 - 25) / 80 = 55 / 80 = 0,6875, soit 68,75 %. Cette valeur appartient à l’intervalle annoncé.
Le calcul demandé compare uniquement le texte codé, sans ajouter le stockage de la table ou de l’arbre et sans arrondir aux octets. Sur un si petit message, ces métadonnées peuvent annuler le gain réel d’un fichier complet : c’est une limite du modèle, pas une erreur du calcul.
Regardez les fréquences fabriquer les codesUn atelier pour expérimenter
Choisissez un message puis avancez les fusions. Le tableau montre la forêt réelle et, à la dernière étape, les codes. Comparez une phrase déséquilibrée à des lettres aussi fréquentes.
Lire le résultat de l’expérience initiale
5/5 fusions : 1 arbre(s)
Le texte occupe 25 bits au lieu de 80, hors table de codage. Les égalités peuvent produire d’autres codes de même coût.
| Symbole | Effectif | Code | Bits contribués |
|---|---|---|---|
| S | 2 | 00 | 4 |
| N | 2 | 01 | 4 |
| SP | 1 | 100 | 3 |
| I | 1 | 1010 | 4 |
| X | 1 | 1011 | 4 |
| A | 3 | 11 | 6 |
Chaque fusion conserve le poids total. Les chemins courts attribués aux symboles fréquents réduisent la somme effectif × longueur du code.
Exercice 3 · 8 points
Gérer les kimonos et les licences d’un club de judo
Un club de judo développe son système d’information pour les inscriptions, communications et compétitions. L’exercice a deux parties indépendantes. Pour les listes abstraites, on utilise des listes Python et la méthode append.
Partie A : locations de kimonos
| Relation | Schéma et clés |
|---|---|
| adherent | numero-licence (clé primaire), taille-adherent, nom, prenom |
| kimono | id-kimono (clé primaire), taille-kimono |
| location | numero-licence et id-kimono (clé primaire composée, également clés étrangères), debut, fin |
location.numero-licence référence adherent.numero-licence ; location.id-kimono référence kimono.id-kimono. Les identifiants de kimonos sont entiers. Les tailles sont en centimètres, multiples de 10 : 100, 110, 120… Les dates sont des chaînes AAAA-MM-JJ. Toutes les valeurs doivent être valides et renseignées, mais fin peut valoir la chaîne vide '' pour une location en cours. COUNT compte les enregistrements. Les mots SQL cités par le sujet sont SELECT, FROM, WHERE, JOIN ON, INSERT INTO, VALUES, COUNT, DELETE.
Les noms de colonnes du sujet contiennent des traits d’union. Les requêtes exécutables ci-dessous les entourent de guillemets doubles, pour ne pas les interpréter comme des soustractions.
Question 1
#Écrire une requête SQL permettant de connaître le numéro des kimonos en cours de location.
Comprendre la correction
SELECT "id-kimono"
FROM location
WHERE fin = '';La convention dit « chaîne vide », pas NULL. Le filtre doit donc utiliser une égalité avec deux apostrophes.
Question 2
#Écrire une requête SQL permettant de connaître le nombre de kimonos de taille 130 cm possédés par le club.
Comprendre la correction
SELECT COUNT(*)
FROM kimono
WHERE "taille-kimono" = 130;On compte les lignes de l’inventaire des kimonos, et non les lignes de location : un kimono jamais loué appartient tout de même au club.
Question 3
#Écrire la requête SQL permettant de connaître le nom et le prénom de l’adhérent qui possède le kimono 42 uniquement si ce kimono est en cours de location. Ne pas renvoyer les anciens locataires.
SQLRetrouver le locataire actuel du kimono 42Écrivez votre solution et mettez-la à l’épreuve
Renvoyez le nom et le prénom de l’adhérent qui loue actuellement le kimono 42. Une location est en cours lorsque fin vaut la chaîne vide ; les anciennes locations doivent être exclues.
SELECT ...
FROM ...
WHERE ...;Les cas de test proposés :
- Schéma officiel, locations pédagogiques : Les deux identités et licences viennent de l’énoncé. Les tailles et les locations sont des cas pédagogiques ajoutés au schéma officiel, qui ne fournit pas de lignes SQL de location.
- Cas complémentaire : aucune location actuelle du 42 : Jeu complémentaire pédagogique, distinct des données officielles. Le kimono 42 a été rendu ; une autre location reste active. Le résultat doit être vide.
Comprendre la correction
SELECT adherent.nom, adherent.prenom
FROM adherent JOIN location
ON adherent."numero-licence" = location."numero-licence"
WHERE location."id-kimono" = 42 AND location.fin = '';La jointure retrouve l’adhérent à partir de sa licence. Les deux conditions du filtre sont indispensables : identifier le kimono et ne conserver que sa location actuelle.
Question 4
#Pour anticiper l’année suivante, le club ajoute arbitrairement 10 cm à la taille de tous ses adhérents mesurant strictement moins de 160 cm. Écrire la requête réalisant cette opération.
Comprendre la correction
UPDATE adherent
SET "taille-adherent" = "taille-adherent" + 10
WHERE "taille-adherent" < 160;La partie droite utilise l’ancienne valeur pour calculer la nouvelle. Un adhérent de 150 cm passe à 160 cm ; celui qui mesure déjà 160 cm ne change pas. Le mot UPDATE, nécessaire à cette question, complète la liste indicative de mots SQL donnée au début.
Question 5
#Le kimono 25 a été déchiré. Écrire les requêtes SQL permettant de le supprimer de la base.
Comprendre la correction
DELETE FROM location WHERE "id-kimono" = 25;
DELETE FROM kimono WHERE "id-kimono" = 25;On supprime d’abord ses locations, qui référencent le kimono, puis sa ligne d’inventaire. L’ordre inverse risquerait de violer une contrainte de référence. Dans un service réel, on pourrait archiver le matériel plutôt qu’effacer son historique ; ici le sujet demande bien la suppression.
Partie B : tableaux d’adhérents
Chaque adhérent possède nom (plus de cinq caractères), prenom, annee (quatre caractères), mois et jour (deux chiffres), et sexe (F ou M). La licence est une chaîne de 16 caractères : sexe, date JJMMAAAA, cinq premières lettres du nom en majuscules, puis deux chiffres de 01 à 99 pour distinguer des personnes partageant ce préfixe.
Les jumelles Clémence et Stéphanie Dupond, nées le 03/07/1997, ont par exemple F03071997DUPON01 et F03071997DUPON02.
Question 6
#Déterminer un numéro de licence possible pour Eddie Nirrer né le 12/10/2021.
Comprendre la correction
M12102021NIRRE01 est un numéro possible, en retenant le sexe masculin supposé par la question et le suffixe disponible 01. On assemble M, 12102021, NIRRE, 01. Le suffixe pourrait être un autre entier de 01 à 99 pour distinguer une collision.
Question 7
#Un adhérent a la licence M23091974MARTI01. Donner sa date de naissance et un nom de famille possible.
Comprendre la correction
Il est né le 23 septembre 1974. Un nom possible est Martin : ses cinq premières lettres, MARTI, correspondent au numéro et il possède plus de cinq caractères. Le numéro ne permet pas de retrouver le nom complet de façon unique.
tab_adherents est une liste de dictionnaires partageant les clés nom, prenom, annee, mois, jour, sexe, numero-licence. Ses deux premières entrées sont :
tab_adherents = [
{'nom': 'DUPOND', 'prenom': 'CLEMENCE', 'annee': '1997',
'mois': '07', 'jour': '03', 'sexe': 'F',
'numero-licence': 'F03071997DUPON01'},
{'nom': 'DUPOND', 'prenom': 'STEPHANIE', 'annee': '1997',
'mois': '07', 'jour': '03', 'sexe': 'F',
'numero-licence': 'F03071997DUPON02'},
# autres adhérents...
]Question 8
#Donner, sans justifier, la valeur de tab_adherents[1]['prenom'].
Comprendre la correction
'STEPHANIE'Question 9
#Écrire l’instruction permettant d’obtenir la valeur 'F03071997DUPON01'.
Comprendre la correction
tab_adherents[0]['numero-licence']On choisit d’abord le dictionnaire de Clémence à l’indice 0, puis la clé qui contient sa licence.
def nombre_adherents(table, annee):
compteur = ...
for adherent in table:
if ...:
...
...Question 10
#Compléter nombre_adherents(table, annee), qui renvoie le nombre d’adhérents nés pendant l’année indiquée par une chaîne de quatre caractères.
Comprendre la correction
def nombre_adherents(table, annee):
compteur = 0
for adherent in table:
if adherent['annee'] == annee:
compteur = compteur + 1
return compteurOn compare deux chaînes de même format. Le compteur augmente pour chaque concordance, et non pour chaque année différente. Une table vide ou une année absente donne 0.
Question 11
#Écrire adherent_plus_age(table), renvoyant la liste des dictionnaires des adhérents les plus âgés. La comparaison porte seulement sur l’année ; garder tous les ex aequo. La table est non vide, personne n’est né après '2024', et la comparaison des années sous forme de chaînes donne le même résultat que celle des entiers.
Indice
Un nouveau minimum efface les anciens candidats ; une égalité les complète.
Comprendre la correction
def adherent_plus_age(table):
annee_min = table[0]['annee']
resultat = []
for adherent in table:
annee = adherent['annee']
if annee < annee_min:
annee_min = annee
resultat = [adherent]
elif annee == annee_min:
resultat.append(adherent)
return resultatUne année plus petite désigne une personne plus âgée. Quand on découvre un nouveau minimum, on remplace la liste des candidats ; quand l’année est égale au minimum, on ajoute l’adhérent. Initialiser à la première année évite un seuil artificiel. L’hypothèse de non-vacuité rend table[0] valide.
Question 12
#Écrire verification_licence(adherent), qui renvoie si la licence correspond au sexe, à la date de naissance et au nom de famille. On dispose de extraire(s, i, j), qui renvoie la sous-chaîne d’indice i inclus à j exclu ; extraire('F03071997DUPON01', 5, 9) vaut '1997'.
PythonDétecter une licence qui ne correspond pas à l’adhérentÉcrivez votre solution et mettez-la à l’épreuve
Écrivez verification_licence(adherent). Les champs sexe, jour, mois, annee et nom sont des chaînes ; jour et mois ont deux caractères. Comparez les quatorze premiers caractères de numero-licence au sexe, à la date JJMMaaaa et aux cinq premières lettres du nom en majuscules. Les noms de ce modèle ont au moins cinq caractères. Le suffixe distingue des homonymes et n’est pas calculable à partir de ces seuls champs : ne le validez pas ici.
def verification_licence(adherent):
# À vous de jouer
passLes cas de test proposés :
- Le nom est normalisé : dupond fournit DUPON ; le nom entier n’est pas encodé.
- Un autre jour de naissance : 03 dans la licence ne doit pas correspondre à 04 dans le dictionnaire.
- Le sexe doit aussi correspondre : Le premier caractère fait partie du contrôle, même si la date et le nom sont corrects.
- Une erreur à la fin du préfixe : Le quatorzième caractère est inclus dans la comparaison ; une tranche trop courte le manquerait.
- Le suffixe n’identifie pas les données civiles : 42 peut distinguer un autre adhérent partageant le même préfixe ; cette question ne contrôle pas l’unicité dans le registre.
Indice
Le préfixe informatif comporte 14 caractères, avant le suffixe de collision.
Comprendre la correction
def verification_licence(adherent):
numero = adherent['numero-licence']
prefixe = (adherent['sexe'] + adherent['jour'] + adherent['mois']
+ adherent['annee'] + adherent['nom'][:5].upper())
return extraire(numero, 0, 14) == prefixeLes quatorze premiers caractères déterminent les renseignements à comparer. Le suffixe de deux chiffres ne se déduit pas du seul dictionnaire : il sert à distinguer des collisions dans le registre. upper() rend la comparaison du nom conforme aux majuscules exigées.
Ce code répond au contrôle de concordance demandé. Pour contrôler en plus le format complet, on peut vérifier une longueur de 16 et un suffixe numérique entre 01 et 99, mais cela ne prouve toujours pas que le numéro est unique dans toute la fédération.
Décodez une licence sans perdre les indicesUn atelier pour expérimenter
Modifiez la date, le début du nom et le suffixe. Le tableau suit les indices exacts de chaque champ, comme la fonction extraire du sujet.
Lire le résultat de l’expérience initiale
F03071997DUPON01
Les bornes droites sont exclues : [5,9) contient 9 - 5 = 4 caractères. Le suffixe distingue des personnes partageant les quatorze premiers caractères ; il ne code pas le prénom.
| Champ | Indices Python | Valeur |
|---|---|---|
| Sexe | [0,1) | F |
| Jour | [1,3) | 03 |
| Mois | [3,5) | 07 |
| Année | [5,9) | 1997 |
| Nom | [9,14) | DUPON |
| Suffixe | [14,16) | 01 |
Un identifiant structuré se lit avec des bornes exactes. La cohérence de ses champs, la validité de son format et son unicité sont trois contrôles différents.
Du sujet à la méthode
Votre prochaine séance de révision
- Pour une question de décidabilité, exposez les deux branches de la contradiction sans chercher à exécuter réellement le programme paradoxal.
- Dans Huffman, fixez un ordre pour les égalités, dessinez les poids, puis utilisez votre propre arbre jusqu’au calcul final.
- Dans le traitement des adhérents, testez un nouveau minimum après plusieurs candidats et plusieurs personnes nées la même année.
Retrouver ces notions dans d’autres sujets
Toutes les annales de NSI · Le guide pour préparer le bac NSI 2027
Énoncé : sujet 25-NSIJ1JA1 (PDF). Corrigé et explications pédagogiques proposés par Sofien.
