Épreuve écrite · 2026 · Jour 1

Bac NSI 2026 Métropole jour 1

Ce sujet du 16 juin 2026 fait passer d’un réseau de lycée à un solitaire binaire, puis à une plateforme de débat. La difficulté commune : traduire une situation en une représentation calculable, sans perdre le sens des données. Les trois exercices indépendants sont à traiter en 3 h 30, sans calculatrice. Les conseils de rédaction ci-dessous sont pédagogiques et ne constituent pas un barème officiel.

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

Réseau du lycée : adressage, routage et confidentialité

Le réseau informatique du lycée relie campus, internat et services administratifs. Chaque site possède un sous-réseau avec son propre adressage IP et une interface de routeur qui lui sert de passerelle. Les liaisons entre routeurs sont celles du schéma suivant ; R5 est relié à Internet.

R5R4R1R3R2
Réseau du lycée : liaisons entre les cinq routeurs
Lire les connexions du schéma
  • R1 relié à R2
  • R1 relié à R3
  • R1 relié à R4
  • R2 relié à R3
  • R2 relié à R4
  • R3 relié à R4
  • R4 relié à R5
SiteSous-réseauRouteur
site1172.16.0.0/20R1
site2172.16.16.0/20R1
site3172.16.32.0/20R2
site4172.16.48.0/20R2
site5172.16.64.0/20R3
site6172.16.80.0/20R3

En notation CIDR a.b.c.d/n, les n bits de poids fort identifient le réseau ; les autres identifient la machine. Les machines d’un même sous-réseau partagent leur partie réseau. Convention du lycée : la passerelle prend la dernière adresse utilisable du sous-réseau et cette adresse est affectée à l’interface du routeur côté site. Pour le site6 : réseau 172.16.80.0, passerelle et interface de R3 172.16.95.254.

Partie A : configuration IP du site3

iface eth0 inet static
   address 172.16.32.15
   netmask 255.255.240.0
   gateway 172.16.48.254

Question 1

#

Convertir sur 32 bits l’adresse IP 172.16.32.15 et le masque 255.255.240.0, sous la forme XXXXXXXX.XXXXXXXX.XXXXXXXX.XXXXXXXX.

Indice

Décomposez chaque octet en puissances de deux ; complétez à gauche avec des zéros.

Comprendre la correction
Adresse IP : 10101100.00010000.00100000.00001111
Masque     : 11111111.11111111.11110000.00000000

Chaque octet doit garder huit chiffres : 172 = 128 + 32 + 8 + 4 ; 16 = 16 ; 32 = 32 ; 15 = 8 + 4 + 2 + 1. Le masque contient vingt bits à 1 consécutifs, donc le préfixe est /20.

Pour vérifier un octet, additionnez uniquement les poids correspondant aux bits à 1 dans la ligne 128, 64, 32, 16, 8, 4, 2, 1. La séparation par des points facilite cette vérification et évite de perdre les zéros initiaux. Le masque binaire n’est pas une adresse de machine : il indique quels bits de l’adresse sont conservés dans la partie réseau.

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

Question 2

#

Indiquer le nombre d’hôtes que ce réseau peut accueillir et les première et dernière adresses IP utilisables.

Indice

Repérez les deux combinaisons réservées : tous les bits hôtes à 0 et tous à 1.

Comprendre la correction

Il reste 32 - 20 = 12 bits pour les hôtes. On obtient 2¹² - 2 = 4 094 adresses utilisables, de 172.16.32.1 à 172.16.47.254. 172.16.32.0 désigne le réseau et 172.16.47.255 la diffusion. La passerelle consomme elle-même une de ces 4 094 adresses si l’on compte les autres équipements à installer.

Dans le troisième octet, les quatre bits de poids fort sont fixes : 0010. Ses quatre bits de poids faible vont de 0000 à 1111, ce qui donne les valeurs 32 à 47. Le dernier octet varie de 0 à 255. Le premier hôte est donc obtenu après l’adresse tout à zéro côté machine, et le dernier avant l’adresse tout à un. Cette méthode fonctionne aussi lorsqu’un masque ne s’arrête pas sur une frontière d’octet.

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

Question 3

#

L’hôte accède aux serveurs et imprimantes du site3, mais pas à Internet. Un test vers 172.16.47.254 réussit. Identifier le paramètre erroné et proposer une correction.

Indice

Une passerelle IPv4 directement accessible doit être dans le sous-réseau de l’hôte.

Comprendre la correction

La passerelle configurée 172.16.48.254 appartient au site4, hors du sous-réseau de l’hôte. Remplacer par gateway 172.16.47.254. Une communication locale n’utilise pas la passerelle ; cela explique pourquoi imprimantes et serveurs restent joignables. Le test confirme que l’interface attendue de R2 est accessible.

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

Question 4

#

Le lien R2-R4 utilise le réseau 192.168.0.8/30. Proposer deux adresses pour les interfaces des routeurs.

Indice

Un /30 contient quatre adresses, dont deux sont utilisables.

Comprendre la correction

Par exemple R2 : 192.168.0.9 et R4 : 192.168.0.10, ou l’inverse. Les quatre adresses vont de .8 à .11 ; .8 est le réseau et .11 la diffusion.

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

Partie B : routage dynamique

Depuis un hôte du site3, l’administrateur obtient :

$ traceroute education.gouv.fr
1  4 ms  7 ms  9 ms  R2 [172.16.47.254]
2 22 ms  6 ms  8 ms  R3 [192.168.0.14]
3 22 ms  7 ms  9 ms  R4 [192.168.0.6]
4 21 ms  6 ms  8 ms  R5 [192.168.0.1]
5 19 ms  7 ms  9 ms  internet-router [...]
6 ...

RIP attribue à une route un coût égal au nombre de liens empruntés.

Question 5

#

En RIP, donner le chemin suivi de R2 à R5 d’après cette trace et son coût.

Indice

Comptez les liens, pas les sommets.

Comprendre la correction

R2 → R3 → R4 → R5, coût 3 : trois liens entre routeurs. L’hôte et le routeur Internet apparaissent dans la trace, mais ne font pas partie du trajet demandé de R2 à R5.

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

Question 6

#

Expliquer le dysfonctionnement et proposer une cause possible.

Indice

Cherchez dans le schéma un chemin de deux liens.

Comprendre la correction

Le trajet R2 → R4 → R5 coûte seulement 2 en RIP. Si toutes les liaisons indiquées sont opérationnelles et les tables convergées, la route observée de coût 3 n’est donc pas optimale. Une panne ou mauvaise configuration de R2-R4, une route non annoncée ou une convergence RIP encore inachevée peut l’expliquer. La trace seule ne permet pas d’identifier laquelle.

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

Le réseau utilise maintenant OSPF avec la formule du sujet coût = 10⁸ / débit.

Question 7

#

Pour une liaison, préciser si l’on souhaite minimiser ou maximiser le débit et le coût.

Indice

Le débit mesure une capacité ; le coût est une métrique de choix de route.

Comprendre la correction

On souhaite maximiser le débit et minimiser le coût. Avec la formule donnée coût = 10⁸ / débit, augmenter le débit réduit le coût. Il faut exprimer le débit en bits par seconde, pas directement en Mbit/s.

Voir la question dans le sujet PDF, p. 4 (nouvel onglet)
LiaisonTechnologieDébit
R1-R2Fast Ethernet100 Mbit/s
R1-R3Fibre optique4 Gbit/s
R1-R4Fast Ethernet100 Mbit/s
R2-R3Ethernet10 Mbit/s
R2-R4Ethernet10 Mbit/s
R3-R4Fibre optique4 Gbit/s
R4-R5Fibre optique4 Gbit/s

Question 8

#

Donner le chemin d’un paquet du site4 vers Internet et préciser son coût.

Indice

Le chemin avec le moins de sauts ne possède pas forcément le coût OSPF minimal.

Comprendre la correction

Les coûts sont 10 en Ethernet, 1 en Fast Ethernet et 0,025 pour la fibre (10⁸/(4 × 10⁹)). Du site4, on rejoint R2, puis R2 → R1 → R3 → R4 → R5 → Internet. Le coût inter-routeurs vaut 1 + 0,025 + 0,025 + 0,025 = 1,075. R2-R4-R5 coûterait 10,025 et R2-R1-R4-R5 coûterait 2,025. Les coûts des liaisons site4-R2 et R5-Internet ne sont pas fournis : on ne les invente pas. On applique ici la métrique théorique du sujet, sans arrondi entier propre à certains équipements réels.

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

Partie C : sécuriser les échanges

Un élève de l’internat, dans le site2, ouvre un logiciel malveillant. Le pirate contrôle son ordinateur et accède au réseau du lycée. Alice, dans le site4, et Bob, dans le site5, commencent ensuite une conversation privée.

Question 9

#

Entre chiffrement symétrique et asymétrique, lequel Alice et Bob doivent-ils préférer pour que le pirate ne connaisse pas le contenu des échanges ? Justifier.

Indice

Le point délicat est de partager une clé secrète quand l’attaquant est déjà présent.

Comprendre la correction

Pour établir un échange alors qu’aucun secret préalable n’est indiqué, ils utilisent un mécanisme asymétrique avec authentification des clés : chacun peut publier sa clé publique sans dévoiler sa clé privée. Envoyer une clé symétrique en clair sur le réseau compromis ne la garderait pas secrète. Une fois un secret établi de façon sûre, un chiffrement symétrique convient parfaitement aux données et est employé en pratique. L’asymétrique seul ne suffit pas contre un pirate actif qui substituerait des clés : certificats ou autre vérification fiable de l’identité sont nécessaires. Si Alice et Bob disposaient déjà d’une clé symétrique partagée secrètement, elle pourrait aussi protéger leur conversation.

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

Question 10

#

Expliquer pourquoi HTTPS protège mieux les échanges que HTTP.

Indice

Distinguez confidentialité, intégrité et authentification.

Comprendre la correction

HTTPS transporte HTTP dans TLS. Il fournit le chiffrement des données en transit, le contrôle de leur intégrité et l’authentification du serveur par un certificat validé. HTTP seul laisse les messages lisibles sur le trajet et ne fournit pas ces garanties. Cela ne protège pas un terminal lui-même compromis et ne signifie pas automatiquement que le serveur ne peut pas lire la conversation : le chiffrement de bout en bout serait une propriété supplémentaire.

Voir la question dans le sujet PDF, p. 5 (nouvel onglet)
RIP et OSPF : le même réseau, deux décisionsUn atelier pour expérimenter

Choisissez le protocole et simulez une coupure du lien direct R2-R4. Suivez le trajet retenu jusqu’à R5 et comparez saut et coût.

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

R2 → R1 → R3 → R4 → R5

Les coûts sont additionnés sur les liens empruntés. La destination R5 est la sortie du lycée ; aucun coût R5-Internet n’est donné.

LiaisonCoût utilisé
R1-R21
R1-R30.025
R1-R41
R2-R310
R2-R410
R3-R40.025
R4-R50.025

RIP minimise les sauts ; OSPF minimise une somme de coûts qui favorise les liaisons rapides.

Revoir les notions de cet exercice

Exercice 2 · 6 points

Recto-Verso : jouer avec XOR et chercher la victoire dans un graphe

Le solitaire Recto-Verso dispose neuf jetons sur un plateau de trois lignes et trois colonnes. Chaque jeton est Recto (noir, représenté par 1) ou Verso (blanc, représenté par 0). Une configuration est l’état de ces neuf jetons. Voici la figure 1, reconstruite avec les mêmes faces :

LigneColonne 1Colonne 2Colonne 3
1○ Verso○ Verso● Recto
2○ Verso○ Verso● Recto
3● Recto● Recto○ Verso

Question 1

#

Justifier que le nombre total de configurations est 2⁹.

Indice

Comptez les choix successifs pour chacun des neuf emplacements.

Comprendre la correction

Les neuf jetons ont chacun deux états, indépendamment des autres. Le principe multiplicatif donne 2 × 2 × … × 2, avec neuf facteurs, soit 2⁹ = 512 configurations. Ce décompte concerne tous les plateaux, pas uniquement ceux atteignables depuis un plateau donné.

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

La victoire consiste à obtenir tous les jetons Recto. Un coup retourne tous les jetons d’une ligne, d’une colonne ou de l’une des deux diagonales, soit huit coups. La figure 2 montre ces possibilités depuis la configuration 67 (001/000/011) :

LigneColonne 1Colonne 2Colonne 3
1○ Verso○ Verso● Recto
2○ Verso○ Verso○ Verso
3○ Verso● Recto● Recto
CoupPlateau obtenuEntier
ligne 1110/000/011387
ligne 2001/111/011123
ligne 3001/000/10068
colonne 1101/100/111359
colonne 2011/010/001209
colonne 3000/001/01010
diagonale 1101/010/010338
diagonale 2000/010/11123

Question 2

#

Depuis la figure 1, la séquence ligne 1, ligne 2, colonne 2 mène-t-elle à la victoire ? Justifier.

Indice

Retourner un jeton noir le rend blanc ; il ne suffit pas de noircir ceux qui étaient blancs.

Comprendre la correction

Non. Les configurations successives sont les suivantes :

ÉtapeLigne 1Ligne 2Ligne 3
Départ001001110
ligne 1110001110
ligne 2110110110
colonne 2100100100

La configuration finale est 292 ; seuls les trois jetons de la première colonne sont noirs. La victoire serait 111/111/111, soit 511.

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

On code Recto par 1 et Verso par 0. La configuration 67 a pour liste [0, 0, 1, 0, 0, 0, 0, 1, 1], lue comme une écriture binaire.

Question 3

#

En détaillant le calcul, donner l’entier représentant la configuration de la figure 1.

Indice

Les zéros initiaux ne changent pas la valeur mais conservent les neuf positions du plateau.

Comprendre la correction

On lit les cases ligne par ligne, de gauche à droite et de haut en bas : 001001110. La valeur est 2⁶ + 2³ + 2² + 2¹ = 64 + 8 + 4 + 2 = 78. Le premier jeton correspond à 2⁸ et le dernier à 2⁰.

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

Question 4

#

Implémenter representant, qui prend une liste de 0 et de 1 et renvoie l’entier correspondant.

Indice

Pour passer du préfixe binaire 101 à 1011, on calcule 2 × 5 + 1.

Comprendre la correction
def representant(bits):
    valeur = 0
    for bit in bits:
        valeur = 2 * valeur + bit
    return valeur

Après chaque itération, valeur représente le préfixe déjà lu. Ajouter un bit à droite double la valeur précédente puis ajoute ce bit. On évite ainsi les erreurs sur les exposants et les conversions implicites de chaîne.

Bit luValeur avantCalculValeur après
102×0+11
012×1+02
122×2+15

Cette trace sur [1,0,1] montre l’invariant du préfixe. Une liste de zéros garde la valeur 0 ; une liste vide donne également 0 selon ce code, même si un plateau du jeu contient toujours neuf bits. Ajouter le bit à la fin plutôt qu’au début est essentiel pour respecter le poids fort placé à gauche.

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

La fonction binaire est disponible : elle renvoie les neuf bits d’un entier. XOR vaut 1 si ses deux bits diffèrent et 0 sinon.

XYX ⊕ Y
000
011
101
110
def xor(b1, b2):
    if b1 == b2:
        return 0
    else:
        return 1

Question 5

#

Implémenter xor_etendu(l_x, l_y), renvoyant la liste XOR de deux listes de bits de même longueur.

Indice

Utilisez la fonction xor fournie sur deux bits, pour chaque position.

Comprendre la correction
def xor_etendu(l_x, l_y):
    resultat = []
    for i in range(len(l_x)):
        resultat.append(xor(l_x[i], l_y[i]))
    return resultat

Les deux listes sont parcourues au même indice. La précondition garantit leurs longueurs égales. Une nouvelle liste est construite : les configurations d’origine ne sont pas modifiées. Pour [1, 1] et [0, 1], on obtient [1, 0].

Le XOR de deux bits est symétrique, mais il faut conserver les positions des cases. Une addition ordinaire ne convient pas : 1+1 vaut2 alors que 1 XOR1 vaut0. On peut tester la réversibilité du résultat : appliquer deux fois xor_etendu avec le même masque doit rendre exactement la liste initiale. Le résultat doit aussi conserver la longueur de l’entrée et ne contenir que0 ou1.

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

X ⊕ 1 inverse X et X ⊕ 0 le conserve. La figure 3 représente donc chaque transition de la figure 2 par un XOR avec le masque du coup. Voici tous les calculs :

CoupMasque67 XOR masque
ligne 1111000000110000011
ligne 2000111000001111011
ligne 3000000111001000100
colonne 1100100100101100111
colonne 2010010010011010001
colonne 3001001001000001010
diagonale 1100010001101010010
diagonale 2001010100000010111
coups_possibles = {
    "ligne 1": [
        1,
        1,
        1,
        0,
        0,
        0,
        0,
        0,
        0
    ],
    "ligne 2": [
        0,
        0,
        0,
        1,
        1,
        1,
        0,
        0,
        0
    ],
    "ligne 3": [
        0,
        0,
        0,
        0,
        0,
        0,
        1,
        1,
        1
    ],
    "colonne 1": [
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0
    ],
    "colonne 2": [
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        1,
        0
    ],
    "colonne 3": [
        0,
        0,
        1,
        0,
        0,
        1,
        0,
        0,
        1
    ],
    "diagonale 1": [
        1,
        0,
        0,
        0,
        1,
        0,
        0,
        0,
        1
    ],
    "diagonale 2": [
        0,
        0,
        1,
        0,
        1,
        0,
        1,
        0,
        0
    ]
}
def configurations_suivantes(config):
    config_bin = ...
    voisins = []
    for ... in ...:
        ...  # ligne facultative
        ... = xor_etendu(..., ...)
        voisins.append(representant(...))
    return voisins

Question 6

#

Recopier et compléter configurations_suivantes pour renvoyer les huit configurations accessibles en un coup.

PythonCalculer huit coups possibles, pas huit coups successifsÉcrivez votre solution et mettez-la à l’épreuve

Écrivez configurations_suivantes(config). config est un entier de 0 à 511 représentant les neuf cases de Recto-Verso, poids fort en haut à gauche. binaire, xor_etendu, representant et coups_possibles sont fournis. Renvoyez les huit configurations obtenues en jouant une seule fois chaque masque sur le même plateau initial. Les tests comparent les ensembles de voisins sans imposer un ordre de parcours.

def configurations_suivantes(config):
    # À vous de jouer
    pass

Les cas de test proposés :

  • Tout est verso : Depuis zéro, chaque voisin est le nombre représenté par le masque lui-même.
  • La configuration 67 du sujet : La première diagonale donne 338 ; les sept autres voisins proviennent eux aussi de 67.
  • Tout est recto : XOR retourne les cases visées : un 1 rencontré avec un masque 1 devient 0, il ne reste pas 1.
  • Un seul bit de poids fort : Le bit de poids fort vaut 256 et occupe la première case, pas la dernière.
  • Conserver les masques pour le prochain appel : Aucun masque n’est un plateau mutable à réutiliser comme accumulateur. Les huit sorties sont distinctes pour ces huit masques.
Indice

Parcourir un dictionnaire fournit ses clés. Récupérez ensuite la liste associée au coup.

Comprendre la correction
def configurations_suivantes(config):
    config_bin = binaire(config)
    voisins = []
    for coup in coups_possibles:
        masque = coups_possibles[coup]
        suivante = xor_etendu(config_bin, masque)
        voisins.append(representant(suivante))
    return voisins

Un bit de masque à 1 retourne la case ; un bit à 0 la préserve. Les huit coups sont appliqués chacun au même plateau de départ, et non successivement au plateau obtenu précédemment. Pour 67, la diagonale 1 donne 338, conformément au résultat binaire et au dictionnaire du sujet.

La conversion vers neuf bits se fait une seule fois avant la boucle. Chaque masque produit une nouvelle liste, ensuite convertie en entier. Les huit résultats forment les voisins du sommet config dans le graphe. Une erreur fréquente serait de remplacer config_bin par suivante à chaque tour : cela décrirait une suite de huit coups, alors que la question demande huit alternatives de premier coup.

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

Partie B : graphe des configurations

Un sommet représente une configuration ; une arête x → y existe lorsqu’un coup autorisé transforme x en y. La victoire est 511. Une configuration perdante n’a aucun chemin vers 511 ; les autres sont gagnantes. Le sujet affirme que 4 est perdante. Le graphe est stocké par dictionnaire :

graphe = {
    0: [...],
    # ...
    67: [387, 123, 68, 359, 209, 10, 338, 23],
    # ...
}

Question 7

#

Montrer que l’existence d’une arête x → y implique celle d’une arête y → x.

Indice

Quel effet a une même ligne retournée deux fois ?

Comprendre la correction

Si le coup de masque m fait passer de x à y, alors y = x ⊕ m. Jouer à nouveau le même coup donne (x ⊕ m) ⊕ m = x : chaque jeton concerné est retourné deux fois. Le coup inverse est donc autorisé et l’arête retour existe.

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

Question 8

#

Comparer le nombre d’entiers nécessaires au stockage par dictionnaire et par matrice d’adjacence, et justifier le choix du dictionnaire.

Indice

Il y a 512 sommets et exactement huit coups distincts depuis chacun.

Comprendre la correction

La matrice comporte 512² = 2¹⁸ entrées. Les listes du dictionnaire contiennent 512 × 8 = 2¹² voisins. En comptant aussi les 512 clés entières, cela fait 2¹² + 2⁹ = 4 608 entiers, contre 262 144 entrées. On ignore ici le surcoût propre aux objets Python, puisque la question demande un nombre d’entiers. Le graphe est peu dense : conserver uniquement les huit voisins par sommet évite les très nombreux zéros de la matrice.

Voir la question dans le sujet PDF, p. 9 (nouvel onglet)
def parcours_profondeur(graphe, configuration, vus):
    vus.append(...)
    for s in ...:
        if s not in vus:
            parcours_profondeur(..., ..., ...)

Question 9

#

Recopier et compléter le parcours en profondeur donné.

Indice

Le premier argument reste le graphe entier ; seul le sommet courant change.

Comprendre la correction
def parcours_profondeur(graphe, configuration, vus):
    vus.append(configuration)
    for s in graphe[configuration]:
        if s not in vus:
            parcours_profondeur(graphe, s, vus)

On marque le sommet avant ses appels récursifs. Tous les appels partagent la même liste vus, ce qui empêche de tourner indéfiniment sur les cycles. Le parcours modifie la liste et n’a pas besoin de renvoyer une valeur.

Par exemple, sur un triangle A-B-C-A, le premier appel marque A ; quand la récursion atteint C et retrouve A parmi ses voisins, le test d’appartenance le bloque. Si le marquage avait lieu après les appels aux voisins, A pourrait être rappelé avant d’être marqué et le cycle ne serait plus arrêté. La liste vus est un objet partagé, ce qui rend visibles les ajouts des appels profonds.

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

Question 10

#

Utiliser parcours_profondeur pour vérifier que 4 est perdante.

Indice

La cible est 111111111 en binaire, pas la configuration 0.

Comprendre la correction
vus = []
parcours_profondeur(graphe, 4, vus)
print(511 not in vus)  # affiche True

Le parcours liste exactement la composante accessible depuis 4. La configuration entièrement noire vaut 2⁹ - 1 = 511. Son absence prouve qu’aucune suite de coups ne mène à la victoire. Tester seulement les huit voisins ne suffirait pas : il faut inclure les suites de plusieurs coups.

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

Question 11

#

Quel parcours est le plus approprié pour trouver une victoire en un minimum de coups : largeur ou profondeur ? Justifier.

Indice

Une file explore les distances par couches.

Comprendre la correction

Le parcours en largeur explore d’abord les configurations à un coup, puis à deux coups, etc. Chaque arête représente un coup de même coût : la première découverte de 511 fournit donc une distance minimale. On peut mémoriser les prédécesseurs pour reconstruire la suite de coups. Le parcours en profondeur trouve un chemin éventuel, sans garantir qu’il soit le plus court.

Voir la question dans le sujet PDF, p. 10 (nouvel onglet)
Retourner les jetons et trouver une route vers 511Un atelier pour expérimenter

Jouez sur les configurations du sujet : retournez les jetons, suivez l’encodage binaire et cherchez les neuf faces noires. Vous pouvez ensuite demander au parcours en largeur de trouver un chemin minimal, ou d’expliquer pourquoi la victoire est inaccessible.

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

67 → 387 avec ligne 1

Depuis le résultat, une solution minimale est : colonne 1, colonne 3, diagonale 1.

CaseAvantMasqueAprès
1011
2011
3110
4000
5000
6000
7000
8101
9101

XOR rend chaque coup réversible. L’accessibilité et le minimum de coups sont deux questions de graphe différentes.

Revoir les notions de cet exercice

Exercice 3 · 8 points

Plateforme de débats : arbres d’arguments et base relationnelle

Une plateforme organise les contributions sous forme arborescente plutôt que dans un simple fil chronologique. Chaque affirmation peut recevoir des arguments pour ou contre, qui sont eux-mêmes des affirmations. Le sujet de débat est le point de départ. Dans la figure originale, le sujet est un parallélogramme, les arguments pour des rectangles arrondis et les arguments contre des hexagones ; les mentions ci-dessous rendent ces rôles explicites. Les deux parties sont indépendantes.

Arbre de débat sur l’objectivité de la science. « Pour » soutient son parent ; « contre » l’attaque.
  • Sujet : La Science est une activité humaine objective.
    • Pour : La Science se base sur les faits, qui sont objectifs par définition.
      • Contre : Les faits observés restent interprétés par des scientifiques.
        • Pour : Les théories scientifiques constituent une généralisation des faits, qui va au-delà des simples faits observés.
    • Pour : La Science promeut l’objectivité dans sa méthode.
      • Pour : La méthode scientifique s’efforce de corriger les biais existants.
    • Contre : La Science est faite par des humains, qui ont leur propre subjectivité.
      • Contre : Les théories scientifiques établies se vérifient quelles que soient les personnes qui les appliquent.
    • Contre : La Science subit des pressions sociales et institutionnelles qui compromettent son objectivité.
      • Pour : La recherche financée par des organismes commerciaux peut tordre les faits.
        • Pour : Les géants pétroliers ont minimisé l’impact de l’effet de serre causé par les énergies fossiles.
        • Pour : Les méfaits du tabagisme sur la santé ont longtemps été sous-estimés par des médecins.
        • Contre : La recherche dispose de financements publics la mettant à l’abri des pressions du privé.
      • Contre : La communauté scientifique elle-même est une institution qui fait valoir l’objectivité scientifique.

Chaque affirmation peut recevoir des likes et des dislikes.

Question 2

#

Un arbre de débat est-il nécessairement binaire ? Justifier.

Indice

Comptez les enfants de la racine dans la figure.

Comprendre la correction

Non. Dans un arbre binaire, chaque nœud a au plus deux enfants. Ici, le sujet possède quatre arguments directs ; un nombre quelconque d’arguments peut être ajouté. Deux catégories, pour et contre, ne signifient pas deux enfants.

Voir la question dans le sujet PDF, p. 12 (nouvel onglet)
class Affirmation:
    def __init__(self, phrase):
        """Création d'un objet Affirmation à partir d'une phrase (str)."""
        self.contenu = phrase
        self.sorte = ""  # "sujet", "pour", "contre" ; vide avant ajout
        self.arguments = []
        self.nb_likes = 0
        self.nb_dislikes = 0

Question 3

#

Donner le nom et le type de chaque attribut de la classe Affirmation.

Indice

Les attributs sont les valeurs affectées à self.nom.

Comprendre la correction
AttributTypeRôle
contenustrPhrase de l’affirmation
sortestrsujet, pour, contre ou chaîne vide avant insertion
argumentslistListe d’objets Affirmation enfants
nb_likesintNombre de likes
nb_dislikesintNombre de dislikes

phrase est un paramètre du constructeur ; ce n’est pas un attribut conservé sous ce nom. self désigne l’instance.

Voir la question dans le sujet PDF, p. 12 (nouvel onglet)
def soutenir(self, argument):
    """Ajoute argument comme argument pour de self.
    Précondition : argument ne doit pas avoir été utilisé
    comme sujet, pour ou contre ; son attribut sorte le vérifie.
    """
    assert argument.sorte == ...
    ... .append(argument)
    argument.sorte = "..."

On dispose aussi d’une méthode contrer similaire qui ajoute un argument contre.

Question 4

#

Compléter les lignes 10 à 12 de soutenir conformément à sa documentation.

Indice

La chaîne vide indique un objet encore inutilisé.

Comprendre la correction
assert argument.sorte == ""
self.arguments.append(argument)
argument.sorte = "pour"

On vérifie que l’argument n’appartient pas encore à l’arbre, on l’ajoute à la liste des enfants de l’affirmation courante, puis on enregistre son rôle. Modifier self.sorte serait une erreur : c’est le nouvel argument qui soutient son parent.

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

Question 5

#

Écrire la méthode nb_contre, qui compte les arguments contre directement rattachés à cette affirmation.

Indice

Filtrez la liste des enfants sur leur attribut sorte.

Comprendre la correction
def nb_contre(self):
    nombre = 0
    for arg in self.arguments:
        if arg.sorte == "contre":
            nombre += 1
    return nombre

On ne parcourt que les enfants directs. La consigne ne demande pas le nombre de contre-arguments dans tout le sous-arbre ; il ne faut donc pas ajouter d’appel récursif ici.

Une affirmation peut avoir un argument pour qui possède lui-même plusieurs arguments contre. Ceux-ci ne sont pas directement rattachés à l’affirmation de départ et ne doivent pas être comptés dans cette méthode. Ce décompte local est précisément la valeur que mystere comparera ensuite à celles des autres nœuds.

Voir la question dans le sujet PDF, p. 12 (nouvel onglet)
def mystere(self):
    m = self.nb_contre()
    for arg in self.arguments:
        candidat = arg.mystere()
        if candidat > m:
            m = candidat
    return m

Question 6

#

Expliquer en une phrase ce que renvoie mystere.

Indice

Repérez le maximum calculé entre la valeur locale et les résultats des appels récursifs.

Comprendre la correction

Elle renvoie le plus grand nombre d’arguments contre directs rattachés à une même affirmation dans le sous-arbre de l’affirmation courante, celle-ci comprise. Le maximum commence avec self.nb_contre(), puis est comparé au maximum de chacun des sous-arbres. Ce n’est ni un total de contre-arguments ni une hauteur.

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

L’évaluation additionne les likes de l’affirmation et les évaluations de ses arguments pour ; elle soustrait ses dislikes et les évaluations de ses arguments contre. Un résultat positif favorise le pour, un résultat négatif le contre. Lignes proposées :

def evaluation(self):
def evaluation():
total = self.nb_likes + self.nb_dislikes
total = self.nb_likes - self.nb_dislikes
total = self.nb_dislikes - self.nb_likes
total = self.nb_likes * self.nb_dislikes
for arg in self.arguments:
for arg in self.arguments_pour:
for arg in self.arguments_contre:
if arg.sorte == "sujet":
if arg.sorte == "pour":
if arg.sorte == "contre":
else:
total = arg.evaluation()
total = total + arg.evaluation()
total = total - arg.evaluation()
total = total * arg.evaluation()
return total
return 1 + total

Question 7

#

En choisissant uniquement les lignes proposées et en adaptant l’indentation, écrire evaluation.

Indice

Traduisez la formule locale puis remplacez chaque contribution enfant par un appel récursif.

Comprendre la correction
def evaluation(self):
    total = self.nb_likes - self.nb_dislikes
    for arg in self.arguments:
        if arg.sorte == "pour":
            total = total + arg.evaluation()
        else:
            total = total - arg.evaluation()
    return total

Une feuille renvoie simplement likes - dislikes. Pour un nœud interne, chaque soutien ajoute son évaluation et chaque opposition la soustrait. Soustraire une opposition d’évaluation négative augmente le score du parent : un argument contre lui-même fortement contesté peut renforcer l’affirmation. Le else convient car un enfant inséré est pour ou contre, jamais sujet.

Prenons un sujet de score local5, un soutien évalué3 et une opposition évaluée-2. L’évaluation du sujet vaut5+3-(-2)=10. Pour obtenir le3 ou le-2 des enfants, la même méthode évalue d’abord tous leurs descendants. Il s’agit donc d’un calcul ascendant : les feuilles fournissent leur différence likes/dislikes, puis chaque parent combine ces valeurs avec le signe du lien. La récursion se termine car l’arbre possède un nombre fini de niveaux.

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

Partie B : utilisateurs et contributions

La plateforme gère plusieurs débats avec un SGBD. On peut employer SELECT, FROM, WHERE, AND, OR, JOIN ... ON, ainsi que INSERT, UPDATE et DELETE.

Question 8

#

Quelles propositions font partie des rôles d’un SGBD ? a) Sécuriser les accès ; b) Assurer l’alimentation électrique des serveurs ; c) Assurer la persistance des données même en cas de panne matérielle ; d) Gérer les accès parallèles de plusieurs utilisateurs ; e) Assurer des connexions HTTPS au serveur.

Indice

Séparez la gestion des données de l’alimentation et du serveur web.

Comprendre la correction

Réponses attendues : a, c et d. Le SGBD gère les droits d’accès, la durabilité et la récupération via journaux/sauvegardes, ainsi que les accès concurrents. L’alimentation relève de l’infrastructure et HTTPS du service réseau/web. La durabilité n’est pas une garantie magique contre toute destruction physique : elle suppose les mécanismes de stockage, de sauvegarde et de reprise adaptés.

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

Le schéma de la figure 2 est reconstruit ci-dessous. La clé primaire est indiquée explicitement, et chaque référence correspond à une clé étrangère :

TableAttributsClé primaireClés étrangères
utilisateurpseudo, email, nom, prenompseudo-
affirmationid_aff, contenu, auteur, sorte, aff_repondue, nb_likes, nb_dislikesid_affauteur → utilisateur.pseudo ; aff_repondue → affirmation.id_aff
reactionaff_reagie, utilisateur, sorte(aff_reagie, utilisateur)aff_reagie → affirmation.id_aff ; utilisateur → utilisateur.pseudo

Une affirmation est de sorte sujet, pour ou contre. Une réponse référence son parent par aff_repondue ; un sujet a NULL. Son texte est contenu. Une réaction, like ou dislike, porte sur aff_reagie. Extraits (auteur et contenu non affichés) :

id_affsorteaff_reponduenb_likesnb_dislikes
0sujetNULL4217
1pour02020
2pour04010
3contre01312
4contre0186
7contre11516
aff_reagieutilisateursorte
0alicelike
1alicedislike
0bobdislike
1bobdislike

Question 9

#

Quel autre attribut de utilisateur aurait aussi pu servir de clé primaire ? Justifier.

Indice

Une clé primaire doit être unique et ne pas être NULL.

Comprendre la correction

L’attribut email, à condition que la plateforme impose une adresse renseignée et unique par compte, peut identifier chaque utilisateur. C’est l’alternative usuelle visée. Le schéma seul ne déclare cependant pas cette contrainte : sans elle, son statut de clé candidate n’est pas démontré. Ni le nom ni le prénom ne garantissent l’unicité.

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

Question 10

#

Écrire la requête donnant le nombre d’affirmations ayant 50 likes ou plus.

Indice

Le sujet rappelle que COUNT(*) compte les lignes du résultat.

Comprendre la correction
SELECT COUNT(*)
FROM affirmation
WHERE nb_likes >= 50;

WHERE filtre d’abord les affirmations ; COUNT(*) compte ensuite les lignes retenues. L’égalité doit être incluse. Le résultat est un nombre unique, pas une liste de likes.

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

Question 11

#

Obtenir les contenus des sujets et leurs nombres de likes, créés par les utilisateurs prénommés Pierre et nommés Durand.

SQLDistinguer les sujets de débat de leurs réponsesÉcrivez votre solution et mettez-la à l’épreuve

Affichez contenu et nb_likes des affirmations de sorte égale à 'sujet' écrites par les utilisateurs dont le prénom est Pierre et le nom Durand. Plusieurs comptes peuvent porter ce nom complet.

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

Les cas de test proposés :

  • Structure de l’extrait, auteurs explicitement ajoutés : Les compteurs 42/17 et 20/20 ainsi que les identifiants 0 et 1 viennent de l’extrait. Le PDF omet leurs auteurs et contenus : ceux-ci et les comptes nécessaires sont donc des compléments pédagogiques.
  • Cas complémentaire : homonymes et deux filtres d’identité : Jeu complémentaire pédagogique, distinct des données officielles. Deux affirmations distinctes produisent les mêmes valeurs projetées : elles doivent rester deux lignes. Chaque partie du nom complet est nécessaire.
Indice

Le lien entre les deux tables est auteur = pseudo. Le filtre sujet reste indispensable.

Comprendre la correction
SELECT a.contenu, a.nb_likes
FROM affirmation AS a
JOIN utilisateur AS u ON a.auteur = u.pseudo
WHERE a.sorte = 'sujet'
  AND u.prenom = 'Pierre'
  AND u.nom = 'Durand';

La jointure associe l’auteur à son compte par la clé, puis les trois conditions doivent être vraies simultanément. On ne suppose pas que le couple nom/prénom identifie une seule personne ; tous les sujets des homonymes correspondants sont retournés.

Pour relire la requête, imaginez les étapes logiques : la jointure produit les couples affirmation/auteur compatibles ; les trois filtres retiennent les sujets écrits par les personnes portant les deux noms demandés ; le SELECT ne conserve que contenu et nb_likes. Cette lecture distingue bien le rôle de chaque clause et permet de détecter un oubli du filtre sorte.

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

Le mot-clé AS donne un alias à une table. Le sujet fournit exactement :

SELECT aff.contenu, rep.contenu
FROM affirmation AS aff JOIN affirmation AS rep
  ON rep.affirmation_repondue = aff.id_affirmation
WHERE rep.nb_likes >= 2 * aff.nb_likes
  AND rep.sorte = 'contre'

Question 12

#

Interpréter en français la requête ci-dessous.

Indice

Interprétez aff comme l’affirmation parent et rep comme la réponse.

Comprendre la correction

L’intention est d’obtenir le texte d’une affirmation et le texte d’une réponse contre cette affirmation, lorsque cette réponse possède au moins deux fois autant de likes que l’affirmation. Les deux alias distinguent le parent et sa réponse. Le SQL imprimé utilise toutefois deux noms absents du schéma : affirmation_repondue et id_affirmation. Pour l’exécuter avec les tables données, la jointure doit être rep.aff_repondue = aff.id_aff. Sans cette correction, la requête échoue ; ce n’est pas une difficulté de compréhension de votre part.

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

... affirmation
SET nb_likes = ...
WHERE ... = ...;

Question 13

#

L’utilisateur i<3descartes aime l’affirmation Cogito ergo sum, d’identifiant 108. Compléter les deux requêtes de mise à jour.

Indice

Il faut conserver la valeur actuelle du compteur puis lui ajouter un.

Comprendre la correction
INSERT INTO reaction
VALUES (108, 'i<3descartes', 'like');

UPDATE affirmation
SET nb_likes = nb_likes + 1
WHERE id_aff = 108;

La première instruction mémorise la réaction dans l’ordre des attributs de la table. La seconde incrémente le compteur existant, sans le remplacer par 1, et ne concerne que l’affirmation 108. On suppose qu’aucune réaction de ce compte sur cette affirmation n’existait déjà, conformément à l’insertion demandée. En application réelle, ces deux opérations seraient regroupées dans une transaction.

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

Le compte i<3rgpd demande l’effacement de ses données. La procédure du sujet conserve les affirmations en remplaçant leur auteur par NULL, supprime toutes les réactions du compte sans modifier les compteurs de likes/dislikes, puis supprime le compte. On suit cette procédure technique imposée ; elle n’est pas une analyse juridique générale de l’anonymisation.

Question 14

#

Pourquoi supprimer les réactions avant le compte utilisateur ?

Indice

Quel attribut de reaction référence le compte à supprimer ?

Comprendre la correction

Chaque réaction référence utilisateur.pseudo par une clé étrangère. Supprimer d’abord le compte laisserait des références sans ligne cible et violerait l’intégrité référentielle, en l’absence d’une suppression en cascade prévue. Les affirmations doivent de même avoir été anonymisées avant la suppression du compte.

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

Question 15

#

Écrire les trois requêtes de suppression des données de i<3rgpd, conformément à la procédure.

Indice

D’abord casser les références au compte, ensuite supprimer la ligne référencée.

Comprendre la correction
UPDATE affirmation
SET auteur = NULL
WHERE auteur = 'i<3rgpd';

DELETE FROM reaction
WHERE utilisateur = 'i<3rgpd';

DELETE FROM utilisateur
WHERE pseudo = 'i<3rgpd';

Cet ordre préserve les clés étrangères. NULL s’écrit sans guillemets : ce n’est pas une chaîne contenant le mot NULL. Les likes et dislikes restent inchangés, car le sujet le demande explicitement. Les clauses WHERE évitent de toucher les autres utilisateurs.

Voir la question dans le sujet PDF, p. 16 (nouvel onglet)
Une opposition contestée peut-elle renforcer le débat ?Un atelier pour expérimenter

Réglez le score local du sujet et celui d’un argument. Changez le rôle pour/contre : observez la différence entre le score de l’argument et sa contribution au parent.

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

Évaluation du sujet : 33

Une opposition est soustraite. Si elle est évaluée négativement, soustraire ce score ajoute une contribution positive.

ÉlémentValeur
Score local25
Score de l’argument-8
Contribution après prise en compte du rôle8

La récursion calcule d’abord la valeur du sous-arbre ; le parent applique ensuite le signe correspondant au lien.

Revoir les notions de cet exercice

Du sujet à la méthode

Votre prochaine séance de révision

  • Pour les réseaux, écrivez les unités des débits avant de calculer les coûts.
  • Pour le solitaire, conservez neuf bits afin de garder la correspondance entre indices et cases.
  • Dans un programme récursif, identifiez la valeur locale et la combinaison des résultats enfants.
  • En SQL, relisez les noms du schéma : le sujet contient une incohérence signalée à la question 12.

Retrouver ces notions dans d’autres sujets

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

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