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
Code matriciel simplifié, binaire et table ASCII
Le « QR code simplifié » du sujet est une grille de 6×8 cases : noir vaut 1, blanc vaut 0, chaque ligne encode un entier puis un caractère ASCII. Il ne s’agit pas du format normalisé d’un QR code réel : aucun repère de position ni code correcteur n’est implémenté ici. Le but est de comprendre la chaîne bits → entier → caractère et son inverse. ASCII associe les codes 0 à 127 ; par exemple 01100001 vaut 97 et correspond àa.
| Ligne | Tuple |
|---|---|
| 1 | (0, 1, 0, 0, 1, 1, 0, 1) |
| 2 | (0, 0, 1, 0, 1, 1, 1, 0) |
| 3 | (0, 1, 0, 0, 1, 0, 0, 0) |
| 4 | (0, 1, 1, 0, 0, 0, 0, 1) |
| 5 | (0, 1, 1, 1, 0, 0, 1, 0) |
| 6 | (0, 1, 1, 0, 0, 0, 0, 1) |
Figure 2 : table ASCII complète, codes 0 à 127
| Codes 0..7 du bloc | +1 | +2 | +3 | +4 | +5 | +6 | +7 |
|---|---|---|---|---|---|---|---|
| 0: NUL | 1: SOH | 2: STX | 3: ETX | 4: EOT | 5: ENQ | 6: ACK | 7: BEL |
| 8: BS | 9: HT | 10: LF | 11: VT | 12: FF | 13: CR | 14: SO | 15: SI |
| 16: DLE | 17: DC1 | 18: DC2 | 19: DC3 | 20: DC4 | 21: NAK | 22: SYN | 23: ETB |
| 24: CAN | 25: EM | 26: SUB | 27: ESC | 28: FS | 29: GS | 30: RS | 31: US |
| 32: espace | 33: ! | 34: " | 35: # | 36: $ | 37: % | 38: & | 39: ' |
| 40: ( | 41: ) | 42: * | 43: + | 44: , | 45: - | 46: . | 47: / |
| 48: 0 | 49: 1 | 50: 2 | 51: 3 | 52: 4 | 53: 5 | 54: 6 | 55: 7 |
| 56: 8 | 57: 9 | 58: : | 59: ; | 60: < | 61: = | 62: > | 63: ? |
| 64: @ | 65: A | 66: B | 67: C | 68: D | 69: E | 70: F | 71: G |
| 72: H | 73: I | 74: J | 75: K | 76: L | 77: M | 78: N | 79: O |
| 80: P | 81: Q | 82: R | 83: S | 84: T | 85: U | 86: V | 87: W |
| 88: X | 89: Y | 90: Z | 91: [ | 92: \ | 93: ] | 94: ^ | 95: _ |
| 96: ` | 97: a | 98: b | 99: c | 100: d | 101: e | 102: f | 103: g |
| 104: h | 105: i | 106: j | 107: k | 108: l | 109: m | 110: n | 111: o |
| 112: p | 113: q | 114: r | 115: s | 116: t | 117: u | 118: v | 119: w |
| 120: x | 121: y | 122: z | 123: { | 124: | | 125: } | 126: ~ | 127: DEL |
Les noms NUL, SOH… etDEL désignent les caractères de contrôle. Le module fourni les représente par ces noms lisibles plutôt que par les caractères de contrôle eux-mêmes.
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 : ascii.py
figure1 = [(0, 1, 0, 0, 1, 1, 0, 1),
(0, 0, 1, 0, 1, 1, 1, 0),
(0, 1, 0, 0, 1, 0, 0, 0),
(0, 1, 1, 0, 0, 0, 0, 1),
(0, 1, 1, 1, 0, 0, 1, 0),
(0, 1, 1, 0, 0, 0, 0, 1)]
dict_ascii = {
0: "NUL", 1: "SOH", 2: "STX", 3: "ETX", 4: "EOT", 5: "ENQ", 6: "ACK", 7: "BEL",
8: "BS", 9: "HT", 10: "LF", 11: "VT", 12: "FF", 13: "CR", 14: "SO", 15: "SI",
16: "DLE", 17: "DC1", 18: "DC2", 19: "DC3", 20: "DC4", 21: "NAK", 22: "SYN", 23: "ETB",
24: "CAN", 25: "EM", 26: "SUB", 27: "ESC", 28: "FS", 29: "GS", 30: "RS", 31: "US",
32: " ", 33: "!", 34: "\"", 35: "#", 36: "$", 37: "%", 38: "&", 39: "'",
40: "(", 41: ")", 42: "*", 43: "+", 44: ",", 45: "-", 46: ".", 47: "/",
48: "0", 49: "1", 50: "2", 51: "3", 52: "4", 53: "5", 54: "6", 55: "7",
56: "8", 57: "9", 58: ":", 59: ";", 60: "<", 61: "=", 62: ">", 63: "?",
64: "@", 65: "A", 66: "B", 67: "C", 68: "D", 69: "E", 70: "F", 71: "G",
72: "H", 73: "I", 74: "J", 75: "K", 76: "L", 77: "M", 78: "N", 79: "O",
80: "P", 81: "Q", 82: "R", 83: "S", 84: "T", 85: "U", 86: "V", 87: "W",
88: "X", 89: "Y", 90: "Z", 91: "[", 92: "\\", 93: "]", 94: "^", 95: "_",
96: "`", 97: "a", 98: "b", 99: "c", 100: "d", 101: "e", 102: "f", 103: "g",
104: "h", 105: "i", 106: "j", 107: "k", 108: "l", 109: "m", 110: "n", 111: "o",
112: "p", 113: "q", 114: "r", 115: "s", 116: "t", 117: "u", 118: "v", 119: "w",
120: "x", 121: "y", 122: "z", 123: "{", 124: "|", 125: "}", 126: "~", 127: "DEL"
}
test1 = [84, 101, 115, 116, 32, 49, 32, 114, 101, 117, 115, 115, 105, 33]
test2 = [84, 101, 115, 116, 32, 50, 32, 114, 101, 117, 115, 115, 105, 33]
test3 = [84, 101, 115, 116, 32, 51, 32, 114, 233, 117, 115, 115, 105, 33]
Code fourni : qrcode.py
import ascii
#############################################################################
# Question 1 et 2 : Écrire les codes des fonctions bin2dec et qrcode2dec
# Proposer un test de qrcode2dec
#############################################################################
# implémentation du QR Code de la figure 1:
qrcode_fig1 = ascii.figure1
#############################################################################
# Question 3 : Fonctions dec2str et test_dec2str
#############################################################################
def dec2str(liste_dec):
""" entrée: liste d'entiers décimaux
sortie: chaine de caractère formée des caractères correspondant
de la table ascii """
table_ascii = ascii.dict_ascii
chaine = ""
for entier in liste_dec:
chaine += table_ascii[entier]
return chaine
def test_dec2str():
""" Teste la fonction dec2str avec des données issues du module fourni """
tests = [ascii.test1, ascii.test2, ascii.test3]
for test in tests:
print(dec2str(test))
def qrcode2str(qrcode):
return dec2str(qrcode2dec(qrcode))
#############################################################################
# Question 4 : Fonction str2qrcode déficiente
#############################################################################
def str2qrcode(message):
"""
Convertit une chaine de caractères en liste de tuples binaires.
"""
qrcode = []
table_inverse = {valeur: cle for cle, valeur in ascii.dict_ascii.items()}
for caractere in message:
entier = table_inverse.get(caractere, 63)
binaire_str = bin(entier)[2:]
ligne = tuple(int(bit) for bit in binaire_str)
qrcode.append(ligne)
return qrcode
Question 1
#Écrire bin2dec, qui reçoit un tuple de bits et renvoie l’entier naturel correspondant. Décoder la figure 1 pour découvrir le nom contenu dans le message.
Indice
Lire le bit suivant revient à doubler la valeur déjà accumulée.
Comprendre la correction
def bin2dec(bits):
valeur = 0
for bit in bits:
valeur = 2 * valeur + bit
return valeurEn lisant de gauche à droite, multiplier par 2 décale la valeur d’une position binaire, puis ajouter le bit incorpore le chiffre courant. Pour 01100001, les valeurs successives sont 0,1,3,6,12,24,48,97. Les six lignes de la figure donnent 77,46,72,97,114,97, donc le message est M. Hara. Le zéro de tête ne change pas la valeur numérique, mais sera indispensable pour dessiner une ligne de largeur fixe à la question 4.
assert bin2dec((0,1,1,0,0,0,0,1)) == 97
assert bin2dec((0,0,0,0,0,0,0,0)) == 0
assert bin2dec((1,1,1,1,1,1,1,1)) == 255La conversion par accumulation se justifie avec un invariant simple : après chaque bit, la variable contient la valeur du préfixe déjà lu. Si ce préfixe vaut v, ajouter un bit b à droite produit 2v + b, exactement comme écrire un chiffre supplémentaire en base 10 produit 10v + chiffre. On peut donc convertir des tuples de longueurs différentes avec le même algorithme. La contrainte de huit bits appartient au format graphique de ce sujet, pas à la règle générale de conversion.
Question 2
#Écrire qrcode2dec, qui transforme une liste de tuples en liste d’entiers. Proposer un test utilisant la figure 1 du module ascii.py.
Comprendre la correction
def qrcode2dec(qrcode):
return [bin2dec(ligne) for ligne in qrcode]assert qrcode2dec(ascii.figure1) == [77,46,72,97,114,97]
assert qrcode2dec([]) == []Chaque ligne produit exactement un entier et l’ordre des lignes est conservé. Réutiliser bin2dec évite de réécrire une conversion déjà testée. Ce test de toute la figure vérifie à la fois les valeurs et leur ordre, ce qu’un test limité au nombre de lignes ne ferait pas.
Question 3
#Exécuter test_dec 2 str. Identifier le problème puis modifier dec2str afin de toujours renvoyer une chaîne lisible.
Indice
Comparer 233 à l’ensemble des clés de dict_ascii.
Comprendre la correction
Les deux premiers tests affichent Test 1 reussi! et Test 2 reussi! avec les espaces du jeu fourni. Le troisième contient 233, absent de la table 0..127 : l’accès par crochets provoque KeyError.233 est utilisé ici pour un caractère accentué dans une autre convention d’encodage, mais cela ne l’ajoute pas à ASCII. Nous adoptons un remplacement visible ? pour tout entier absent.
def dec2str(liste_dec):
chaine = ''
for entier in liste_dec:
chaine += ascii.dict_ascii.get(entier, '?')
return chaineassert dec2str(ascii.test3) == 'Test 3 r?ussi!'
assert dec2str([65,233,66]) == 'A?B'
assert dec2str([]) == ''
test_dec2str()Le remplacement conserve un signe visible à l’endroit non décodable et évite de masquer la perte. Supprimer la valeur inconnue raccourcirait silencieusement le message. Cette convention n’invente pas le caractère original : il faut connaître l’encodage source pour le retrouver exactement.
Question 4
#str2qrcode ne reproduit pas exactement la figure 1 pour son message. Identifier l’origine et modifier le code pour obtenir des lignes valides de huit bits.
PythonEncoder un message sans perdre les zéros de têteÉcrivez votre solution et mettez-la à l’épreuve
Corrigez str2qrcode(message). Chaque caractère devient un tuple de huit bits à partir de la table ascii.dict_ascii fournie. Un caractère absent est remplacé par le code 63, celui de ?. Renvoyez les lignes dans l’ordre du message. Cet atelier reconstruit les données du dessin, sans bibliothèque graphique.
def str2qrcode(message):
# À vous de jouer
pass
Les cas de test proposés :
- Figure 1 du sujet : L’égalité vérifie chaque bit et l’ordre des six lignes.
- Le point demande deux zéros initiaux : 46 s’écrit 101110 en binaire minimal, mais le dessin demande huit cases.
- Espace et zéro : Un espace est un caractère avec un code, pas une ligne à supprimer.
- Caractère absent : La convention du sujet remplace le caractère inconnu par ?, sans inventer son encodage.
- Tous les caractères ASCII imprimables : La reconstruction indépendante par les poids binaires vérifie les 95 caractères imprimables.
- Message vide : Aucun caractère ne produit aucune ligne.
Indice
Comparer la longueur binaire de 46 et celle attendue pour une ligne.
Comprendre la correction
bin(entier)[2:] supprime le préfixe 0 b, mais ne complète pas les zéros de tête. Le point 46 est écrit 101110 sur 6 bits au lieu de 00101110 sur 8. Il faut imposer la largeur avant de créer le tuple.
def str2qrcode(message):
table_inverse = {caractere: entier for entier, caractere in ascii.dict_ascii.items()}
qrcode = []
for caractere in message:
entier = table_inverse.get(caractere, 63)
binaire = bin(entier)[2:].zfill(8)
qrcode.append(tuple(int(bit) for bit in binaire))
return qrcodeassert str2qrcode('M.Hara') == ascii.figure1
assert all(len(ligne) == 8 for ligne in str2qrcode('M.Hara ?'))
assert str2qrcode('é') == [(0,0,1,1,1,1,1,1)]La dernière assertion vérifie la convention déjà fournie : un caractère absent est remplacé par 63, le code de?. zfill(8) conserve la valeur tout en fixant le format graphique. Les valeurs de la table étant au plus 127, huit bits suffisent. Le dictionnaire représente les contrôles par des noms commeLF ; parcourir une chaîne LF traite deux lettres, pas un retour à la ligne. La réversibilité attendue concerne donc les caractères imprimables pris en charge.
Le test aller-retour doit distinguer deux propriétés. Pour un caractère ASCII imprimable reconnu, décoder ce que l’on vient d’encoder doit restituer ce caractère. Pour un caractère non pris en charge comme é, le programme fourni prévoit un remplacement par ?, donc cet aller-retour ne peut pas restituer l’original. Il faut le dire au lieu de promettre une conversion sans perte pour tout texte. Le test d’égalité avec la figure 1 contrôle en plus les zéros initiaux et le nombre exact de cases par ligne.
Valeur numérique et largeur graphiqueUn 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
- 101110 et 00101110 ont…
La même valeur, des largeurs différentes.. Les zéros initiaux ne changent pas l’entier.
- Le code 233 est-il un code ASCII de cette table ?
Non, les clés vont de 0 à 127.. La borne de la table fournie est 127.
Appuyez votre explication sur les valeurs et les conditions exactes du programme.
Assembler un octet, lire son caractèreUn atelier pour expérimenter
Changez les huit bits. Chaque position affiche son poids. La valeur décimale est convertie selon ASCII ; hors 0..127, le remplacement? est affiché.
Lire le résultat de l’expérience initiale
01001101 = 77 ; caractère : M.
Chaque bit1 apporte son poids. Le premier bit doit être0 pour rester dans la plage ASCII0..127.
| Position | Bit | Poids | Contribution |
|---|---|---|---|
| 0 | 0 | 128 | 0 |
| 1 | 1 | 64 | 64 |
| 2 | 0 | 32 | 0 |
| 3 | 0 | 16 | 0 |
| 4 | 1 | 8 | 8 |
| 5 | 1 | 4 | 4 |
| 6 | 0 | 2 | 0 |
| 7 | 1 | 1 | 1 |
Une donnée combine une valeur, une largeur de représentation et une convention de décodage.
Du sujet à la méthode
Votre prochaine séance de révision
- Tester séparément conversion numérique et format des lignes.
- Un remplacement de caractère doit être explicite car il perd de l’information.
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_22 (PDF). Corrigé et explications pédagogiques proposés par Sofien.
