Bac 2025 : NSI, Métropole jour 1

Aller à un exercice ou une partie

Proposition de corrigé — non officielle. Session 2025. Voie générale — spécialité NSI, Métropole, 17 juin 2025. Durée : 3 heures 30.

Ouvrir le sujet officiel · Télécharger une copie du sujet · Retrouver les annales

Les réponses expliquent les raisonnements et les calculs. Pour les compositions et les analyses, plusieurs réponses argumentées sont possibles ; cette proposition n’est pas validée par le jury.

Exercice 1 — Collection de guitares et SQL

Partie A — Une seule table

1. Une clé primaire identifie chaque ligne sans ambiguïté. Le numéro 81757532 apparaît pour une Gibson et une Fender : num_ser n’est donc pas unique dans toute la table.

2. Le résultat contient deux lignes :

marquemodele
GibsonLes Paul Goldtop
FenderStratocaster

Sur téléphone, faites défiler le tableau horizontalement.

3. Les années du modèle recherché s’obtiennent avec :

SELECT annee
FROM inventaire
WHERE modele = 'Les Paul Standard';

4. Le tri demandé porte sur les années, même si l’on affiche les modèles :

SELECT modele
FROM inventaire
WHERE marque = 'Gibson'
ORDER BY annee ASC;

5. La condition sur la clé évite de modifier plusieurs guitares :

UPDATE inventaire SET annee = 1957 WHERE id = 1;

Partie B — Trois tables reliées

6. Il faut créer marque, puis modele, puis guitare. Chaque table dépend de la précédente par une clé étrangère qui doit référencer une table existante.

7. La jointure relie chaque guitare à son modèle :

SELECT guitare.num_ser, guitare.annee
FROM guitare
JOIN modele ON guitare.id_modele = modele.id
WHERE modele.nom = 'Les Paul Standard';

8. DELETE FROM guitare WHERE id = 3;

On retire la guitare, pas le modèle, qui peut encore être associé à d’autres instruments.

9. Les insertions respectent également l’ordre des dépendances :

INSERT INTO marque (id, nom) VALUES (3, 'BC Rich');
INSERT INTO modele (id, nom, id_marque)
VALUES (5, 'Mockingbird', 3);
INSERT INTO guitare (id, id_modele, annee, num_ser, prix)
VALUES (9, 5, 1992, '92R', 5000);

10.

SELECT SUM(guitare.prix)
FROM guitare
JOIN modele ON guitare.id_modele = modele.id
WHERE modele.nom = 'Stratocaster';

Sur l’extrait fourni, la somme vaut 215 000 €.

Exercice 2 — File de priorité et planning

Questions 1 à 3 — Les objets Tache

tache1 = Tache(1, "Répondre aux e-mails", 45)
tache2 = Tache(2, "Ranger ma chambre", 60)

Les deux méthodes à placer dans la classe sont :

def avancer(self, n):
    self.duree_restante -= n

def est_terminee(self):
    return self.duree_restante <= 0

Une durée restante négative est autorisée par l’énoncé : cela signifie simplement que la tâche s’est achevée avant la fin du créneau.

Questions 4 à 6 — État de la file

4. Après insertion de t6, puis de t7 :

Début → (t3,4) (t7,4) (t1,3) (t2,3) (t6,2) (t4,1) (t5,1) → Fin

La nouvelle tâche de priorité 4 vient après t3 : l’ordre d’arrivée est conservé à priorité égale.

5. En repartant de la file initiale, f.defiler()[0] renvoie l’objet t3. La file devient (t1,3) (t2,3) (t4,1) (t5,1).

6. Toujours en repartant de la file initiale, f.examiner()[1] renvoie 4. La file reste inchangée, car examiner ne retire aucun élément.

Questions 7 et 8 — Insérer sans perdre la stabilité

def ajouter_file_prio(f, t, p):
    f_aux = File()
    while not f.est_vide() and f.examiner()[1] >= p:
        f_aux.enfiler(f.defiler())
    f_aux.enfiler((t, p))
    while not f.est_vide():
        f_aux.enfiler(f.defiler())
    while not f_aux.est_vide():
        f.enfiler(f_aux.defiler())

Le test de vacuité doit précéder l’examen du premier élément. L’opérateur >= fait passer les anciennes tâches de même priorité avant la nouvelle. En supposant les opérations élémentaires de file de coût constant, le coût est linéaire, O(m) : chaque élément est transféré un nombre constant de fois. Les boucles se succèdent ; elles ne sont pas imbriquées.

Questions 9 et 10 — Le planning Pomodoro

Les 17 créneaux successifs sont :

1–5   : t3, t7, t3, t3, t3
6–10  : t1, t2, t1, t2, t2
11–13 : t6, t6, t6
14–17 : t4, t5, t4, t5

Le planning dure 425 minutes, repos de fin de créneau compris. Une tâche inachevée rejoint l’arrière du groupe ayant sa priorité, mais passe toujours avant les tâches moins prioritaires.

def planning(f):
    resultat = []
    while not f.est_vide():
        t, p = f.defiler()
        resultat.append(t)
        t.avancer(25)
        if not t.est_terminee():
            ajouter_file_prio(f, t, p)
    return resultat

Cette fonction vide la file et modifie les durées restantes des objets, comme le prévoit le déroulement proposé.

Exercice 3 — Réseaux et arbres binaires de recherche

Partie A — Adressage

1. Les réponses sont a et b : 192.168.20.2 et 192.168.20.157. L’octet 261 est impossible et 192.168.24.10 appartient à un autre réseau avec le masque fourni.

2. L’adresse de diffusion est 192.168.20.255.

3. Un /24 offre 256 adresses, dont deux réservées. Après installation, trois bornes et l’interface du routeur occupent quatre adresses : il reste 254 − 4 = 250 adresses de machines. Le switch n’en utilise pas dans le modèle du sujet.

4. Pour huit adresses au total, il faut trois bits pour la partie hôte : 2³ = 8. Le préfixe maximal est donc /29, soit 255.255.255.248. Ce nouveau découpage demanderait de réexaminer les adresses attribuées : il ne conserve pas automatiquement toutes celles du /24 initial.

Partie B — Routage RIP

5. Les lignes manquantes sont :

DestinationInterface de sortieProchain routeurSauts
192.168.30.0172.16.4.1172.16.4.21
172.16.1.0172.16.3.1172.16.3.21

Sur téléphone, faites défiler le tableau horizontalement.

6. Le réseau du siège 192.168.10.0 peut aussi être atteint en deux sauts par R2 → R3 → R4. La ligne peut donc porter l’interface 172.16.4.1, le prochain routeur 172.16.4.2 et le coût 2.

7. La route par défaut utilise l’interface 172.16.3.1 et la passerelle 172.16.3.2, vers R1, connecté à Internet.

Partie C — Routage OSPF

8. Le Fast Ethernet coûte 10⁹/10⁸ = 10 et la fibre 10⁹/10⁹ = 1.

9. Le meilleur trajet de R1 à R4 est R1 → R2 → R3 → R4, de coût 10 + 10 + 1 = 21. Le lien direct R1–R4 coûte 100 ; le passage R1–R3–R4 coûte 101. Le plus petit nombre de sauts ne donne donc pas ici le plus faible coût OSPF.

La figure 2 inverse les libellés « café 1 » et « café 2 » par rapport à la figure 1. Cela ne change pas les liaisons entre routeurs nécessaires à cette question ; les réponses d’adressage utilisent la figure 1, explicitement visée dans la partie A.

Partie D — Comparaison et recherche

10. ip_bin('192.168.20.12') renvoie :

11000000.10101000.00010100.00001100

11–12. La dernière instruction est atteinte lorsque les deux adresses sont égales. L’ordre demandé étant strict, elle renvoie False :

def precede(ip_1, ip_2):
    for i in range(35):
        if ip_1[i] < ip_2[i]:
            return True
        elif ip_1[i] > ip_2[i]:
            return False
    return False

Les points occupent les mêmes positions dans les deux chaînes et n’affectent donc pas la comparaison.

13. adresse_ip est un attribut ; est_vide est une méthode.

14. La méthode est :

def est_vide(self):
    return self.adresse_ip == ''

15. Une recherche dans un ABR suit un seul chemin. Son coût est proportionnel à sa hauteur : O(log n) si l’arbre est équilibré, mais O(n) dans le pire cas d’un arbre dégénéré. Le seul fait d’être un ABR ne garantit donc pas une recherche logarithmique.

16. Il faut tester la vacuité avant de changer l’adresse :

def modifie(self, adresse_ip, interface, passerelle, cout):
    if self.est_vide():
        self.gauche = Abr('', '', '', 0)
        self.droite = Abr('', '', '', 0)
    self.adresse_ip = adresse_ip
    self.interface = interface
    self.passerelle = passerelle
    self.cout = cout

17. La ligne 35 devient :

elif precede(ip_bin(adresse_ip), ip_bin(self.adresse_ip)):

On convertit les adresses décimales en chaînes binaires de longueur fixe avant de les comparer. Une comparaison directe de chaînes décimales donnerait un ordre incorrect dans certains cas.