Épreuve écrite · 2026 · Jour 2

Bac NSI 2026 centres étrangers groupe 1 jour 2

Ce sujet traverse une application de taxis, une collection d’ordinateurs anciens et les composants d’une machine. Les 38 questions numérotées, dont les sept opérations de la question 12 du dernier exercice sont traitées séparément, donnent 44 étapes corrigées. Les simulations permettent de suivre les coûts, les routes et le contenu réel d’un tampon circulaire. Durée : 3 h 30 sans calculatrice.

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é.

Exercice 1 · 6 points

Compagnie de taxis : objets, durée, tarif et échange de clés

Une application Python gère une compagnie de taxis. Les constructeurs et méthodes suivants sont disponibles ; les noms d’attributs sont conservés exactement.

ClasseAttributs initialisés
Chauffeurnom (str), prenom (str), neph (str) : les trois paramètres du constructeur. Le NEPH est un identifiant de douze chiffres dans le contexte du sujet.
Clientnom (str), prenom (str), adresse (str), nb_personne (int) : les quatre paramètres. nb_personne compte les personnes accompagnant le client.
Taxiimmatriculation (str), type_vehicule (str), energie (str), adaptation (bool) : les quatre paramètres ; libre=True ; chauffeur=None.
Courseclient (Client), taxi (Taxi), depart (str), destination (str) : les quatre paramètres ; date_depart=None et date_arrivee=None, destinées à recevoir des datetime.
MéthodeContrat
Taxi.est_libre()Renvoie le booléen libre
Taxi.modifier_libre(statut)Modifie libre, ne renvoie rien
Taxi.choix_chauffeur(chauffeur)Affecte un objet Chauffeur, ne renvoie rien
Course.distance()Renvoie la distance du trajet en km (float)
Course.temps()Renvoie la durée du trajet en minutes (float)

Les adresses sont des chaînes comme « 42 rue de l’Informatique, Octet-sur-Mer, France ». La capacité d’un véhicule compte les passagers en plus du conducteur. Les tarifs sont ceux de cet exercice :

vehicules = {
  "standard": {
    "capacite": 4,
    "prix_km": 1.1,
    "prise_en_charge": 3,
    "tarif_horaire": 38
  },
  "monospace": {
    "capacite": 8,
    "prix_km": 1.8,
    "prise_en_charge": 9,
    "tarif_horaire": 60
  },
  "minibus": {
    "capacite": 19,
    "prix_km": 3,
    "prise_en_charge": 50,
    "tarif_horaire": 100
  }
}
energie = ["hybride", "électrique", "thermique"]

Chaque classe est définie dans chauffeur.py, client.py, taxi.py ou course.py ; les données sont dans donnees.py, l’application dans application.py. Tous ces fichiers sont dans le même répertoire.

Question 1

#

Écrire les imports dans application.py pour utiliser les données et les quatre classes.

Indice

Un fichier Python est importé par son nom de module sans extension.

Comprendre la correction
from donnees import vehicules, energie
from chauffeur import Chauffeur
from taxi import Taxi
from client import Client
from course import Course

Le nom du module est celui du fichier sans .py. Les noms des classes conservent leur majuscule. Ces imports permettent d’employer directement Chauffeur, Taxi, etc., sans préfixe de module. Les classes doivent aussi importer dans leur propre module les dépendances qu’elles utilisent : un import dans application.py ne crée pas automatiquement un nom global dans course.py.

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

Question 2

#

Instancier le chauffeur John Doe, NEPH 140159320012.

Indice

Respectez les types et l’ordre du constructeur.

Comprendre la correction
john = Chauffeur("Doe", "John", "140159320012")

Le NEPH est une chaîne conformément au contrat, même s’il ne contient que des chiffres. Le nom précède le prénom dans les paramètres. Aucun calcul arithmétique n’a de sens sur cet identifiant.

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

Question 3

#

Créer le taxi HG-818-AV, standard électrique non adapté PMR, et l’attribuer à John Doe.

Indice

La relation taxi/chauffeur est une référence vers un objet, pas une chaîne.

Comprendre la correction
taxi_john = Taxi("HG-818-AV", "standard", "électrique", False)
taxi_john.choix_chauffeur(john)

L’objet Chauffeur existant est transmis à la méthode ; on ne transmet pas uniquement son nom. False représente l’absence d’adaptation. La création initialise déjà libre à True.

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

Question 4

#

Écrire l’assertion au début du constructeur de Course pour refuser un taxi occupé.

Indice

Appelez la méthode booléenne sur le taxi reçu en paramètre.

Comprendre la correction
assert taxi.est_libre(), "Ce taxi est déjà occupé"

taxi désigne ici le paramètre du constructeur, disponible avant l’affectation éventuelle à self.taxi. Il faut appeler est_libre avec des parenthèses : tester l’objet méthode lui-même ne lirait pas son résultat. L’assertion exprime la précondition pédagogique ; dans un service concurrent réel, l’attribution nécessiterait une opération atomique pour empêcher deux réservations simultanées.

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

Question 5

#

Ajouter l’instruction marquant le taxi occupé lors de la création de la course.

Indice

Le statut libre devient False dès l’affectation à la course.

Comprendre la correction
taxi.modifier_libre(False)

Après validation de sa disponibilité, la création de la course réserve ce même objet Taxi. Si self.taxi a déjà été affecté, self.taxi.modifier_libre(False) est équivalent. Ne pas affecter le résultat de la méthode à une variable : son rôle est de modifier l’état et elle ne renvoie rien.

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

Question 6

#

Créer la cliente Jeanne Doe accompagnée de ses deux enfants, puis sa course de 6 rue des ordinateurs, Paris à 211 avenue Jean Jaurès, Paris.

Indice

Relisez si le champ compte les accompagnants ou tous les passagers.

Comprendre la correction
jeanne = Client("Doe", "Jeanne",
                "6 rue des ordinateurs, Paris, France", 2)
course_jeanne = Course(jeanne, taxi_john,
                      jeanne.adresse,
                      "211 avenue Jean Jaurès, Paris, France")

nb_personne vaut 2 accompagnants, et non 3 : le contrat décrit les personnes en plus de la cliente. Il y a donc trois passagers au total, compatibles avec la capacité 4 du véhicule standard. La course référence la cliente et le taxi existants ; les dates ne sont pas encore renseignées.

Voir la question dans le sujet PDF, p. 6 (nouvel onglet)
from datetime import datetime
depart = datetime(2025, 7, 12, 9, 12)
arrivee = datetime(2025, 7, 12, 17, 12)
(arrivee - depart).total_seconds()  # 28800.0

Question 7

#

Écrire Course.temps(), durée entre les deux dates en minutes.

Indice

La méthode datetime fournit des secondes, alors que le contrat demande des minutes.

Comprendre la correction
def temps(self):
    return (self.date_arrivee - self.date_depart).total_seconds() / 60

La soustraction de datetime produit un timedelta. total_seconds inclut toute la durée, y compris les jours éventuels ; diviser par 60 donne des minutes. L’attribut seconds seul ne représente pas toujours la durée totale. On suppose que les deux dates sont renseignées et que l’arrivée suit le départ.

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

Exemple : prise en charge 3 €, prix/km 1,10 €, tarif horaire 38 €, trajet 9,1 km en 19 min. Le montant attendu arrondi est 25,04 €.

def tarif(self):
    type_vehicule = ...
    donnees_tarifaire = vehicules[type_vehicule]
    prise_en_charge = ...
    tarif_h = ...
    prix_km = ...
    tarif = ...
    tarif = tarif + prix_km * ...
    tarif = tarif + tarif_h * ... / 60
    return tarif

Question 8

#

Compléter Course.tarif selon la prise en charge, la distance et la durée.

Indice

Vérifiez les unités de chaque produit et distinguez attributs et méthodes.

Comprendre la correction
def tarif(self):
    type_vehicule = self.taxi.type_vehicule
    donnees_tarifaire = vehicules[type_vehicule]
    prise_en_charge = donnees_tarifaire["prise_en_charge"]
    tarif_h = donnees_tarifaire["tarif_horaire"]
    prix_km = donnees_tarifaire["prix_km"]
    tarif = prise_en_charge
    tarif = tarif + prix_km * self.distance()
    tarif = tarif + tarif_h * self.temps() / 60
    return tarif

Le type du véhicule permet de choisir le sous-dictionnaire des tarifs. La méthode distance renvoie des kilomètres et temps des minutes. Le terme horaire doit donc diviser ces minutes par 60. Pour 9,1 km et 19 minutes en standard : 3 + 1,10×9,1 + 38×19/60 = 25,0433… €, soit 25,04 € affichés au centime. Le programme demandé renvoie le calcul brut ; une politique d’arrondi monétaire relèverait de l’application.

Le module course.py doit avoir accès à vehicules, par exemple avec from donnees import vehicules. Les méthodes distance et temps doivent être appelées ; multiplier une méthode sans parenthèses serait une erreur de type.

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

Partie B : communication avec la centrale

L’application doit protéger les messages entre la centrale et les chauffeurs.

Question 9

#

Distinguer les fonctionnements des chiffrements symétrique et asymétrique.

Indice

La différence porte sur le secret partagé ou la paire de clés complémentaires.

Comprendre la correction

Le symétrique partage un même secret pour chiffrer et déchiffrer. L’asymétrique utilise une paire de clés : un message chiffré pour un destinataire avec sa clé publique est déchiffré par sa clé privée, qu’il conserve secrète. La clé publique peut être connue de tous, mais son association au bon destinataire doit être authentifiée.

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

La centrale génère une clé symétrique aléatoire, l’envoie au chauffeur sans traitement, puis l’utilise pour chiffrer les messages.

Question 10

#

Quel problème pose l’envoi direct de la clé de session avant les messages chiffrés ?

Indice

Un chiffrement ne protège plus les messages contre quelqu’un qui possède déjà sa clé.

Comprendre la correction

Un observateur qui intercepte la clé envoyée en clair peut ensuite déchiffrer les messages de cette session. Le fait que la clé soit aléatoire ne protège pas sa transmission. Il faut préserver son secret pendant l’établissement de la communication, pas seulement chiffrer les données suivantes.

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

Question 11

#

Proposer une stratégie détaillée pour transmettre la clé de session de façon sûre tout en gardant un chiffrement rapide des échanges.

Indice

Le message chiffré avec la clé publique du chauffeur doit être ouvert uniquement par sa clé privée.

Comprendre la correction

Le chauffeur possède une paire asymétrique et garde sa clé privée secrète. La centrale obtient sa clé publique et vérifie son authenticité, par exemple par un certificat validé. Elle génère la clé symétrique de session et la chiffre avec cette clé publique ; le chauffeur la récupère avec sa clé privée. Les deux parties utilisent ensuite la clé de session pour un chiffrement symétrique authentifié des messages, adapté aux gros volumes.

L’asymétrique sert ainsi à établir ou protéger le secret de session, tandis que le symétrique traite le trafic courant. Sans authentification de la clé publique, un attaquant actif pourrait lui substituer la sienne. En pratique, on s’appuie sur un protocole éprouvé comme TLS plutôt que d’assembler soi-même ce dialogue ; l’exercice décrit le principe hybride.

Voir la question dans le sujet PDF, p. 7 (nouvel onglet)
Lire le détail d’un tarif de courseUn atelier pour expérimenter

Choisissez le véhicule, la distance et la durée. Le modèle sépare la prise en charge, les kilomètres et le temps pour repérer les erreurs de conversion.

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

Montant : 25.04 €

La durée entre dans le calcul horaire sous la forme minutes/60. Les tarifs sont exclusivement ceux de l’exercice.

ComposanteCalculMontant (€)
Prise en charge33.00
Distance1.1 × 9.110.01
Durée38 × 19/6012.03

La structure objet relie une course à son taxi ; le sous-dictionnaire de tarifs et les unités complètent le calcul.

Revoir les notions de cet exercice

Exercice 2 · 6 points

VintagePixel : collection relationnelle et choix des routes

Ada restaure des ordinateurs des années 1980 et 1990. Elle gère d’abord la relation ordinateur(id_ordi INT, marque TEXT, modele TEXT, etat TEXT), de clé primaire id_ordi. SQL autorise SELECT, FROM, WHERE, AND, OR, JOIN ... ON, INSERT, UPDATE, DELETE, DISTINCT, ORDER BY et COUNT(*).

id_ordimarquemodeleetat
5Atari1040 STFonctionnel
6CommodoreCommodore 64Réparation
7SinclairZX SpectrumFonctionnel
8CommodoreAmiga 500Fonctionnel
9AppleApple IIeRéparation
10CommodoreVic 20Fonctionnel
11SinclairZX 81Panne
12Atari800 XLFonctionnel

Question 1

#

Lister les modèles en réparation de la collection.

SQLRetrouver les ordinateurs en réparationÉcrivez votre solution et mettez-la à l’épreuve

Renvoyez les modèles des ordinateurs dont l’état est Réparation, d’après la table ordinateur de la partie A. Panne et Fonctionnel sont des états distincts.

SELECT ...
FROM ...
WHERE ...;

Les cas de test proposés :

  • Collection officielle avant les mises à jour : Ces états sont ceux du premier tableau de l’exercice, avant la réparation ultérieure de l’Apple IIe.
  • Cas complémentaire : panne ne veut pas dire réparation : Jeu complémentaire pédagogique, distinct des données officielles. Une seule ligne est en réparation. Le modèle est la colonne à afficher, la marque ne doit pas la remplacer.
Indice

Réparation et Panne sont deux valeurs distinctes du champ état.

Comprendre la correction
SELECT modele FROM ordinateur
WHERE etat = 'Réparation';

Le filtre reprend exactement la valeur stockée. Dans l’extrait initial, les modèles sont Commodore 64 et Apple IIe. Le résultat ne contient ni les modèles simplement en panne, ni ceux déjà fonctionnels.

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

Question 2

#

Insérer un Thomson MO5 en panne avec id_ordi 22.

Indice

Utilisez la structure de table en vigueur à cette étape de l’énoncé.

Comprendre la correction
INSERT INTO ordinateur (id_ordi, marque, modele, etat)
VALUES (22, 'Thomson', 'MO5', 'Panne');

On renseigne les quatre attributs du schéma de la partie A. id_plat sera ajouté seulement dans la partie suivante.

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

Question 3

#

L’Apple IIe d’identifiant 9 est restauré. Mettre son état à jour.

Indice

Une mise à jour individuelle doit être limitée à la bonne clé.

Comprendre la correction
UPDATE ordinateur
SET etat = 'Fonctionnel'
WHERE id_ordi = 9;

La clé primaire cible l’ordinateur exact. Filtrer seulement la marque Apple pourrait modifier plusieurs machines.

Voir la question dans le sujet PDF, p. 9 (nouvel onglet)
SELECT COUNT(*) FROM ordinateur
WHERE marque = 'Commodore' AND etat = 'Fonctionnel';

Question 4

#

Donner COUNT(*) pour marque Commodore ET état Fonctionnel.

Indice

Les deux conditions doivent être satisfaites sur la même ligne.

Comprendre la correction

2 : Amiga 500 et Vic 20. Commodore 64 est en réparation, donc exclu. La restauration de l’Apple IIe ne change pas ce résultat puisque sa marque n’est pas Commodore.

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

Partie B : plateformes et jeux

Ordinateur id_ordiid_platÉtat à cette étape
52Fonctionnel
61Réparation
75Fonctionnel
83Fonctionnel
94Fonctionnel
106Fonctionnel
118Panne
129Fonctionnel
id_jeutitregenreetatid_plat
12LemmingsPuzzleComplet3
13BarbarianActionSans notice1
14PopulousStratégieComplet2
15Knight LoreAventureLoose5
16Dungeon MasterRPGComplet2
id_platnombits
1C648
2Atari ST16
3Amiga16
4Apple II8
5Spectrum8

Ce sont des extraits : les plateformes 6,8,9 référencées peuvent exister sans être affichées.

Question 5

#

Donner les schémas relationnels avec domaines de jeu et plateforme.

Indice

Déduisez les domaines des valeurs fournies sans oublier les clés.

Comprendre la correction
RelationSchéma et domainesClé primaireClé étrangère
jeuid_jeu INT, titre TEXT, genre TEXT, etat TEXT, id_plat INTid_jeuid_plat → plateforme.id_plat
plateformeid_plat INT, nom TEXT, bits INTid_plat-

id_plat a le même domaine entier dans les tables qui le référencent. Les états des jeux (« Complet », « Sans notice », « Loose ») sont des textes. La relation ordinateur possède désormais elle aussi une clé étrangère id_plat vers plateforme.id_plat.

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

Question 6

#

Lister les titres compatibles avec la plateforme Oric présents dans la collection.

Indice

Reliez le jeu à sa plateforme puis filtrez son nom.

Comprendre la correction
SELECT j.titre
FROM jeu AS j
JOIN plateforme AS p ON j.id_plat = p.id_plat
WHERE p.nom = 'Oric';

Le nom de plateforme ne se trouve pas dans jeu, donc la jointure est nécessaire. Oric n’apparaît pas dans l’extrait, mais on ne conclut pas qu’il est absent de la base entière. La requête ne limite pas les jeux à un état particulier.

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

Question 7

#

Lister les titres compatibles avec le modèle Amstrad 6128 de la collection.

Indice

Le lien passe par l’égalité de plateforme, pas par le nom du constructeur.

Comprendre la correction
SELECT DISTINCT j.titre
FROM jeu AS j
JOIN ordinateur AS o ON j.id_plat = o.id_plat
WHERE o.modele = 'Amstrad 6128';

La compatibilité est modélisée par une même plateforme : les deux clés étrangères peuvent donc être comparées directement. Une jointure supplémentaire avec plateforme serait correcte mais inutile pour ce résultat. DISTINCT évite les répétitions si Ada possède plusieurs exemplaires du modèle. L’état de fonctionnement de l’ordinateur n’est pas un critère de compatibilité demandé.

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

Partie C : serveurs de jeux en réseau

VintagePixel relie des serveurs A (arcade, via R1), S (stratégie, via R3), P (plateforme, via R7), C (course, via R4). Ada est reliée au LAN de R6 ; Alan et Grace partagent un switch et le LAN de R8. Grace possède 192.168.208.11 avec masque 255.255.255.240. Les liaisons inter-routeurs du dessin sont :

LiaisonTechnologie
R1-R3FE
R1-R6FE
R2-R3E
R2-R6F
R2-R5F
R2-R4F
R6-R5F
R6-R7E
R5-R4FE
R5-R8FE
R4-R8E
R7-R8FE
FEFEEFFFFEFEFEEFER1R3R2R6R4R5R7R8
Topologie de VintagePixel
Lire les connexions du schéma
  • R1 relié à R3 : FE
  • R1 relié à R6 : FE
  • R2 relié à R3 : E
  • R2 relié à R6 : F
  • R2 relié à R5 : F
  • R2 relié à R4 : F
  • R6 relié à R5 : F
  • R6 relié à R7 : E
  • R5 relié à R4 : FE
  • R5 relié à R8 : FE
  • R4 relié à R8 : E
  • R7 relié à R8 : FE

F : fibre 1 Gbit/s ; FE : Fast Ethernet 100 Mbit/s ; E : Ethernet 10 Mbit/s. Alan ne parvient d’abord pas à se connecter au réseau local.

Question 8

#

Quelle commande Alan doit-il utiliser pour tester la connectivité vers Grace ?

Indice

Le test vise l’adresse IP de la machine de Grace.

Comprendre la correction
ping 192.168.208.11

ping envoie des requêtes d’écho vers cette adresse. Des réponses confirment une connectivité IP pour ce test. Une absence de réponse n’identifie pas à elle seule la cause : configuration, liaison, pare-feu ou filtrage ICMP peuvent intervenir.

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

Question 9

#

Convertir 240 en binaire, puis déterminer le nombre de machines encore ajoutables sur ce LAN.

Indice

Comptez les adresses utilisables, puis celles des deux ordinateurs et de la passerelle.

Comprendre la correction

240 = 11110000₂. Le masque fixe 28 bits, donc le réseau 192.168.208.0/28 contient 16 adresses dont 14 utilisables (.1 à .14). Alan et Grace en occupent deux. L’interface LAN du routeur R8 en utilise aussi une pour permettre l’accès aux autres réseaux : il reste donc 11 adresses pour de nouvelles machines, en supposant aucun autre équipement IP sur ce LAN.

Si l’on ne décomptait que les deux ordinateurs, on obtiendrait 12, mais on oublierait l’adresse nécessaire de la passerelle R8 dessinée. Un switch non administré n’a pas besoin d’une adresse IP pour commuter les trames ; un switch administré pourrait en consommer une supplémentaire, ce que le sujet ne précise pas.

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

La table initiale fournit R5 via R5 en1 saut, R6 via R7 en2 sauts et R7 via R7 en1 saut.

Question 10

#

Compléter les quatre premières lignes de la table RIP simplifiée de R8 : destinations R1 à R4.

Indice

La colonne de passerelle indique seulement le premier routeur du chemin.

Comprendre la correction
DestinationRouteur suivant possibleSauts
R1R5 ou R73
R2R5 ou R42
R3R5 ou R43
R4R41
R5R51
R6R7 (fourni) ou R52
R7R71

RIP compte uniquement les liaisons. Pour R1, R8-R5-R6-R1 et R8-R7-R6-R1 sont ex æquo. Pour R3, les routes via R5-R2 ou R4-R2 ont trois liens. Le lien lent direct R8-R4 reste le plus court en sauts vers R4.

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

Question 11

#

Donner un chemin possible pour un message d’Alan vers Ada.

Indice

Alan rejoint R8 et Ada est sur le réseau de R6.

Comprendre la correction

Alan → switch local → R8 → R5 → R6 → Ada. Le trajet R8-R7-R6 est aussi un plus court chemin en deux liaisons inter-routeurs sous RIP. Les liens Ethernet/Fast Ethernet/fibre ne modifient pas le nombre de sauts.

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

OSPF utilise les coûts F=1, FE=10 et E=100.

Question 12

#

Avec OSPF, déterminer le chemin de R8 à R3 pour Grace vers le serveur S et son coût.

Indice

Le lien R2-R3 est Ethernet, donc de coût100, contrairement aux fibres autour de R2.

Comprendre la correction

R8 → R5 → R6 → R1 → R3, coût 10 + 1 + 10 + 10 = 31. Le trajet à trois liens R8-R5-R2-R3 coûte 10+1+100 = 111 ; la liaison R2-R3 est donc à éviter. Passer de R5 à R6 directement coûte1, moins que R5-R2-R6 de coût2. L’itinéraire retenu utilise plus de sauts mais minimise leur somme pondérée.

Voir la question dans le sujet PDF, p. 12 (nouvel onglet)
RIP et OSPF sur les serveurs VintagePixelUn atelier pour expérimenter

Choisissez la destination et la métrique. Le modèle compare tous les chemins simples du petit réseau et affiche les meilleures routes, y compris les égalités.

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

Coût minimal : 31

Une ligne correspond à une route ; seules les dix meilleures sont affichées. Le coût RIP est le nombre de liens, le coût OSPF la somme des poids.

RouteCoûtStatut
R8 → R5 → R6 → R1 → R331Optimale
R8 → R5 → R2 → R6 → R1 → R332Plus coûteuse
R8 → R5 → R4 → R2 → R6 → R1 → R342Plus coûteuse
R8 → R5 → R2 → R3111Plus coûteuse
R8 → R5 → R6 → R2 → R3112Plus coûteuse
R8 → R5 → R4 → R2 → R3121Plus coûteuse
R8 → R4 → R2 → R6 → R1 → R3122Plus coûteuse
R8 → R4 → R2 → R5 → R6 → R1 → R3123Plus coûteuse
R8 → R7 → R6 → R1 → R3130Plus coûteuse
R8 → R4 → R5 → R6 → R1 → R3131Plus coûteuse

La route optimale dépend de la métrique ; les égalités doivent être reconnues plutôt que cachées.

Revoir les notions de cet exercice

Exercice 3 · 8 points

Architecture, additionneur binaire et mémoire tampon circulaire

Les deux parties sont indépendantes. La première étudie une architecture à programme enregistré, où la RAM contient instructions et données, puis quelques opérations d’assembleur et un circuit logique. La seconde modélise un tampon FIFO par un tableau circulaire. Les règles d’assembleur sont celles du modèle simplifié du sujet.

Question 1

#

Quel scientifique donne son nom au modèle d’architecture de 1945 présenté ?

Indice

Le nom attendu est celui de l’architecture à mémoire commune instructions/données.

Comprendre la correction

John von Neumann. Le modèle porte son nom et partage une même mémoire pour le programme et ses données. Cette désignation historique ne signifie pas que toute l’informatique à programme enregistré résulte du travail d’une seule personne.

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

Figure1 reconstruite par ses blocs : à gauche le bloc1 ; à droite une enveloppe2 contenant le bloc3 au-dessus du bloc4. L’accumulateur est dans4. La RAM échange avec3 et4 ; 3 et4 échangent entre eux ; entrées et sorties rejoignent le bloc4.

[1 : mémoire] ⇄ [2 : processeur]
                 ├─ [3 : contrôle]
                 └─ [4 : calcul + accumulateur] ⇄ Entrées / Sorties

Question 2

#

Associer Mémoire RAM, Processeur, Unité arithmétique et logique et Unité de contrôle aux numéros1 à4.

Indice

Le processeur est l’ensemble qui contient les deux unités internes.

Comprendre la correction
NuméroComposant
1Mémoire RAM
2Processeur
3Unité de contrôle
4Unité arithmétique et logique (UAL)

Le grand bloc2 regroupe l’unité de contrôle et l’UAL. Le bloc4 contient l’accumulateur et réalise les opérations sur les données. La RAM échange instructions et données avec le processeur ; les entrées/sorties sont reliées comme indiqué sur le schéma.

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

Question 3

#

Que signifie RAM volatile ?

Indice

Comparez la conservation des données après arrêt de la machine.

Comprendre la correction

Son contenu est perdu lorsque l’alimentation électrique n’est plus maintenue. Une sauvegarde sur un support non volatil, comme un disque, est nécessaire pour conserver les informations après extinction. Volatile ne signifie pas que le contenu change aléatoirement pendant un fonctionnement normal.

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

Question 4

#

Classer registre, cache, RAM et disque dur du plus rapide au plus lent.

Indice

Le registre est directement dans le processeur.

Comprendre la correction

Registre → mémoire cache → mémoire vive (RAM) → disque dur. Cette hiérarchie rapproche les petites mémoires rapides du processeur et utilise des stockages plus grands mais plus lents pour le reste. Elle décrit l’ordre attendu dans le modèle du cours.

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

Le processeur n’exécute pas directement le texte Python. Un langage assembleur donne des noms lisibles à des opérations proches du langage machine. Le modèle du sujet dispose de huit registres r1 à r8 et d’étiquettes qui repèrent des instructions.

InstructionEffet du modèle
addi rA,rB,vrA ← rB + valeur immédiate v
add rA,rB,rCrA ← rB + rC
sub rA,rB,rCrA ← rB - rC
beq rA,rB,labelSaut si rA = rB
bne rA,rB,labelSaut si rA ≠ rB
bgt rA,rB,labelSaut si rA > rB
ble rA,rB,labelSaut si rA ≤ rB

Exemple : si r7>r6, affecter r2+3 à r5, puis dans tous les cas incrémenter r5 :

ble r7, r6, SUITE
addi r5, r2, 3
SUITE:
addi r5, r5, 1

Question 5

#

Écrire l’instruction mettant dans r2 la valeur de r5 moins celle de r4.

Indice

La syntaxe est destination, premier terme, second terme.

Comprendre la correction
sub r2, r5, r4

Le registre destination est le premier opérande. L’ordre des deux sources compte : r5-r4 n’est pas interchangeable avec r4-r5.

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

Question 6

#

Expliquer l’instruction imprimée add r1 r2 0.

Indice

Distinguez add à trois registres et addi avec une valeur immédiate.

Comprendre la correction

L’intention est de copier la valeur de r2 dans r1, en lui ajoutant zéro. Mais selon la distinction fournie dans le tableau, add attend trois registres et 0 n’est pas un des registres r1 à r8. L’écriture cohérente avec le modèle est addi r1, r2, 0. Si une notation désigne explicitement un registre zéro, une addition avec ce registre peut aussi copier une valeur ; cette convention n’est pas définie dans le sujet.

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

Question 7

#

Échanger r1 et r2 avec r3 temporaire.

Indice

Sauvegardez la valeur qui serait écrasée par la première affectation.

Comprendre la correction
addi r3, r1, 0
addi r1, r2, 0
addi r2, r3, 0

La première instruction sauvegarde r1 dans r3 avant qu’il soit écrasé. La seconde copie r2 dans r1 ; la troisième remet l’ancienne valeur de r1 dans r2. r3 est modifié, ce qui est autorisé. Deux copies sans sauvegarde perdraient la première valeur.

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

La figure2 fournit les portes classiques. NOT inverse un bit. Pour les entrées (a,b) dans l’ordre00,01,10,11 :

PorteSorties pour00,01,10,11
AND0,0,0,1
NAND1,1,1,0
OR0,1,1,1
NOR1,0,0,0
XOR0,1,1,0
NXOR1,0,0,1

Figure3 : E1 et E2 entrent dans un premier XOR ; son résultat et Re entrent dans un second XOR qui donne S. Un AND relie le premier XOR à Re ; un autre AND relie E1 et E2 ; leurs sorties entrent dans un OR qui donne Rs. Cette reconstruction conserve tous les fils utiles du circuit.

E1E2ReXZYSRs
Circuit additionneur : X = E1 XOR E2, Y = X AND Re, Z = E1 AND E2
Lire les connexions du schéma
  • E1 vers X
  • E2 vers X
  • E1 vers Z
  • E2 vers Z
  • X vers Y
  • Re vers Y
  • X vers S
  • Re vers S
  • Y vers Rs
  • Z vers Rs
E1E2ReRsS
00000
001AB
01001
01110
10001
101C0
11010
1111D

Question 8

#

Compléter A,B,C,D dans la table de vérité du circuit.

Indice

La sortie S est un XOR à trois entrées ; Rs vaut1 si au moins deux entrées valent1.

Comprendre la correction

A=0, B=1, C=1, D=1. Posons X = E1 XOR E2. Le schéma calcule S = X XOR Re et Rs = (E1 AND E2) OR (X AND Re). Pour 0,0,1 : X=0, S=1 et Rs=0. Pour 1,0,1 : X=1, S=0 et Rs=1. Pour 1,1,1 : X=0, S=1 et Rs=1.

E1E2ReRsS
00000
00101
01001
01110
10001
10110
11010
11111
Voir la question dans le sujet PDF, p. 15, 16 (nouvel onglet)

Question 9

#

Que fait ce circuit d’après la table complétée ?

Indice

Interprétez le couple (Rs,S) comme un nombre binaire de deux bits.

Comprendre la correction

C’est un additionneur complet d’un bit. Il additionne E1, E2 et une retenue entrante Re. S est le bit de somme et Rs la retenue sortante : E1 + E2 + Re = 2×Rs + S. Par exemple1+1+1=3 s’écrit11 en binaire, donc Rs=1 et S=1. On peut chaîner plusieurs circuits en transmettant la retenue à l’étage du bit suivant.

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

Partie B : mémoire tampon

Un tampon stocke temporairement des données pour synchroniser deux processus de rythmes différents. Il fonctionne comme une file, en conservant l’ordre d’enregistrement.

Question 10

#

FIFO ou LIFO : quel terme correspond à une file ?

Indice

La sortie suit l’ordre chronologique des entrées.

Comprendre la correction

FIFO, First In First Out : premier entré, premier sorti. Un tampon conserve ainsi l’ordre des données reçues même si producteur et consommateur travaillent à des rythmes différents.

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

Dans le tableau circulaire, fin est l’indice du prochain emplacement d’ajout, exclu de la file actuelle. Après la dernière case, il revient à0. Retirer avance debut sans effacer la case. Le sujet garantit que le tampon n’atteint jamais sa capacité maximale : debut=fin signifie uniquement vide. Figure4, trace complète :

OpérationContenu physiquedebutfinValeur retirée
Initial[None,None,None,None,None]00-
Ajouter1[1,None,None,None,None]01-
Ajouter2[1,2,None,None,None]02-
Ajouter3[1,2,3,None,None]03-
Retirer[1,2,3,None,None]131
Retirer[1,2,3,None,None]232
Retirer[1,2,3,None,None]333
Ajouter4[1,2,3,4,None]34-
Ajouter5[1,2,3,4,5]30-
Ajouter6[6,2,3,4,5]31-
Retirer[6,2,3,4,5]414
Retirer[6,2,3,4,5]015
class Tampon:
    def __init__(self, capacite):
        self.capacite = capacite
        self.contenu = [None for i in range(capacite)]
        self.debut = 0
        self.fin = 0

    def ajouter_element(self, element):
        self.contenu[self.fin] = element
        self.fin += 1
        if self.fin == self.capacite:
            self.fin = 0

    def retirer_element(self):
        ...

    def est_vide(self):
        return ...

Question 11

#

Que vaut memoire.contenu après memoire = Tampon(5) ?

Indice

La capacité fixe la longueur physique, pas le nombre d’éléments en attente.

Comprendre la correction
[None, None, None, None, None]

Le tableau physique possède toujours cinq cases. La file logique est vide parce que debut et fin valent tous deux0. Les cases None ne constituent pas les éléments de la file ; ce sont seulement les valeurs initiales de stockage.

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

Figure 5 : contenu = [4,6,9,None,None], debut=0, fin=3. Les opérations a à g s’enchaînent sur ce même tampon de capacité 5 ; retirer ne supprime jamais la valeur physique de la liste.

Question 12a

#

À partir de la figure5, retirer un élément. Donner état et retour.

Indice

Seul debut avance après lecture de la tête.

Comprendre la correction

Retour 4. Contenu inchangé [4,6,9,None,None] ; debut=1, fin=3. La file logique restante est [6,9]. Le4 reste en mémoire mais n’appartient plus à la file.

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

Question 12b

#

Puis ajouter10. Donner le nouvel état.

Indice

On écrit à l’ancien indice fin, puis on avance fin.

Comprendre la correction

Contenu [4,6,9,10,None] ; debut=1, fin=4. La file logique est [6,9,10]. L’ajout n’a pas de valeur de retour utile.

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

Question 12e

#

Puis ajouter3. Donner le nouvel état.

Indice

Après l’indice4 dans une capacité5, l’indice suivant est0.

Comprendre la correction

Contenu [4,6,9,10,3] ; debut=3, fin=0. La file logique est [10,3]. Le prochain emplacement d’ajout revient au début du tableau, car l’ancienne fin était l’indice4.

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

Question 12f

#

Puis retirer un élément. Donner état et retour.

Indice

Un indice fin plus petit que debut est normal dans un tableau circulaire.

Comprendre la correction

Retour 10. Contenu [4,6,9,10,3] ; debut=4, fin=0. La file logique contient seulement [3].

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

Question 12g

#

Enfin retirer un élément. Donner état et retour.

Indice

La tête revient à0 et rejoint la fin.

Comprendre la correction

Retour 3. Contenu [4,6,9,10,3] ; debut=0, fin=0. La file est désormais vide même si la liste physique contient cinq nombres. C’est l’égalité des indices, et non les valeurs stockées, qui définit cet état dans le modèle.

Voir la question dans le sujet PDF, p. 18 (nouvel onglet)
memoire = Tampon(5)
memoire.ajouter_element("n")
memoire.ajouter_element("s")
memoire.ajouter_element("i")
memoire.retirer_element()
memoire.ajouter_element("n")
memoire.ajouter_element("f")
memoire.retirer_element()
memoire.ajouter_element("o")

Question 13

#

Donner contenu après le programme de caractères n,s,i, retrait, n,f, retrait, o.

Indice

La question demande la liste physique contenu, pas seulement la file logique restante.

Comprendre la correction
["o", "s", "i", "n", "f"]

Les ajouts remplissent d’abord les indices0,1,2. Le premier retrait avance debut à1. Les ajouts n et f occupent3 et4, puis fin revient à0. Le second retrait avance debut à2. Enfin o remplace l’ancien n à l’indice0 et fin devient1. La file logique est donc ["i","n","f","o"] avec debut=2 et fin=1 ; l’ancien s reste physiquement à l’indice1 mais est hors de la file.

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

Question 14

#

Compléter est_vide.

Indice

Le contenu des cases n’indique pas quelles valeurs appartiennent encore à la file.

Comprendre la correction
return self.debut == self.fin

Cette égalité est suffisante sous l’hypothèse du sujet que la capacité maximale n’est jamais atteinte. Sans cette hypothèse, le même couple d’indices pourrait désigner vide ou plein ; il faudrait un compteur, un indicateur supplémentaire ou garder une case inutilisée.

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

Question 15

#

Écrire retirer_element, file supposée non vide, sans effacer réellement la valeur.

PythonRetirer un élément en avançant dans une mémoire circulaireÉcrivez votre solution et mettez-la à l’épreuve

Complétez retirer_element dans Tampon. La file est supposée non vide et les ajouts des tests ne la saturent jamais : la représentation donnée n’a pas de compteur pour distinguer vide et plein. Renvoyez la valeur en tête, avancez debut avec retour à zéro après la dernière case, et ne modifiez ni contenu ni fin. Il ne faut pas effacer physiquement l’ancienne valeur ni décaler les autres cases.

class Tampon:
    def __init__(self, capacite):
        self.capacite = capacite
        self.contenu = [None for _ in range(capacite)]
        self.debut = 0
        self.fin = 0

    def ajouter_element(self, element):
        self.contenu[self.fin] = element
        self.fin = (self.fin + 1) % self.capacite

    def est_vide(self):
        return self.debut == self.fin

    def retirer_element(self):
        # Lisez la tête, puis avancez debut
        pass

Les cas de test proposés :

  • Lire avant d’avancer : La valeur de tête est à l’ancienne position de debut, pas à la nouvelle.
  • Respecter FIFO et retrouver une file vide : Trois retraits suivent l’ordre d’arrivée, et debut finit par rejoindre fin.
  • Passer de la dernière case à zéro : Le retrait de D à l’indice 3 doit replier debut vers 0, où se trouve E.
  • Ne pas effacer la mémoire : La case A devient logiquement libre, mais sa valeur peut rester jusqu’au prochain écrasement.
  • La queue ne bouge pas lors d’un retrait : fin désigne le prochain emplacement d’insertion ; seul debut change ici.
Indice

Sauvegardez la valeur de tête, avancez circulairement puis renvoyez la valeur sauvegardée.

Comprendre la correction
def retirer_element(self):
    element = self.contenu[self.debut]
    self.debut += 1
    if self.debut == self.capacite:
        self.debut = 0
    return element

La tête est lue avant d’avancer son indice. On replie l’indice après la dernière case. L’écriture équivalente self.debut = (self.debut + 1) % self.capacite exprime le même comportement. Aucun décalage des autres valeurs n’est effectué : l’opération a un coût constant, contrairement à un pop(0) sur une liste Python. Un appel sur file vide devrait être refusé dans une interface complète, mais le sujet garantit la précondition.

Voir la question dans le sujet PDF, p. 18 (nouvel onglet)
Voir le tableau physique et la file logique séparémentUn atelier pour expérimenter

Choisissez l’un des deux programmes du sujet et avancez dans ses opérations. Les valeurs hors de la file restent visibles pour comprendre pourquoi elles ne sont pas forcément effacées.

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

File logique : [4, 6, 9]

Les indices définissent la file de debut inclus à fin exclu en tournant modulo5. Une case hors de cette zone peut conserver une ancienne valeur.

IndiceContenu physiqueDans la file ?Repère
04Ouidebut
16Oui
29Oui
3NoneNonfin
4NoneNon

Le tampon circulaire retire logiquement par un indice, sans déplacer ni effacer les données. Le rangement physique et l’ordre FIFO sont donc différents.

Revoir les notions de cet exercice

Du sujet à la méthode

Votre prochaine séance de révision

  • Lorsque plusieurs modules interviennent, vérifiez où chaque nom est importé.
  • Annoncez ce qui est compté : passagers, accompagnants, adresses IP, sauts ou coûts pondérés.
  • Pour les mémoires circulaires, tracez toujours contenu, debut et fin dans trois colonnes distinctes.

Retrouver ces notions dans d’autres sujets

Toutes les annales de NSI · Le guide pour préparer le bac NSI 2027

Énoncé : sujet 26-NSIJ2G11 (PDF). Corrigé et explications pédagogiques proposés par Sofien.