mots clés : numération binaire, les graphes, récursivité
🔎 Voir les exercices similaires ↓
Métropole – Bac NSI 2026 – Jour 1 Énoncé de l'exercice 2
Cet exercice porte sur le binaire, les graphes, la récursivité.
Le jeu du Recto-Verso, de la famille des solitaires, se compose de neuf jetons disposés sur un plateau carré. Le plateau a 3 lignes et 3 colonnes. Chaque jeton possède une face Recto, dessinée en couleur noire sur les figures, et une face Verso, dessinée en blanc.
Partie A : représentation binaire des configurations
On appelle configuration l’état du plateau. La figure 1 illustre un exemple de configuration.

Justifier que le nombre total de configurations possibles est 29.
Le but du jeu est, depuis une configuration quelconque, de retourner tous les jetons sur leur face Recto (noire). Pour ce faire, le seul type d’opération autorisé est de choisir une ligne ou une colonne ou une diagonale, et d’en retourner tous les jetons. On appelle une telle opération un coup. La figure 2 illustre les huit différents coups possibles à partir d’une configuration donnée.

Indiquer en justifiant si la séquence de coups suivante, jouée depuis la configuration donnée en figure 1, permet de mener à la victoire : ligne 1, ligne 2, colonne 2.
Une configuration est représentée, ligne par ligne et de haut en bas, par une liste de bits en considérant les jetons Recto comme des 1 et les jetons Verso comme des 0. Ainsi on lit la configuration initiale de la figure 2 comme la liste [0, 0, 1, 0, 0, 0, 0, 1, 1].
On peut aussi lire la liste de bits d’une configuration comme l’écriture binaire d’un nombre entier. Pour l’exemple de la figure 2, la configuration initiale est donc aussi représentée par l’entier 67.
En détaillant le calcul, donner l’entier représentant la configuration illustrée en figure 1.
Implémenter une fonction representant prenant en paramètre une liste de 0 et de 1 et renvoyant l’entier correspondant.
Dans la suite on considère à disposition une fonction binaire prenant réciproquement en paramètre un entier et renvoyant son écriture en binaire sous forme d’une liste de neuf 0 ou 1.
L’opérateur ou exclusif, noté ⊕, a pour table de vérité :
| X | Y | X ⊕ Y |
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
La fonction xor définie ci-dessous prend en paramètres deux bits b1, b2 (de type int) et renvoie le résultat de b1 ⊕ b2.
1 def xor(b1, b2):
2 if b1 == b2:
3 return 0
4 else:
5 return 1
L’opérateur ⊕ peut être appliqué sur deux listes de même longueur l_x et l_y contenant plusieurs bits : pour chaque indice de ces listes, on applique le ⊕ aux deux bits positionnés à cet indice. Par exemple, si l_x = [1, 1] et l_y = [0, 1], alors l_x ⊕ l_y vaut [1, 0], puisque 1 ⊕ 0 vaut 1, et 1 ⊕ 1 vaut 0.
Implémenter une fonction xor_etendu qui prend en paramètre deux listes de bits de même longueur l_x et l_y et renvoie la liste l_x ⊕ l_y.
On peut observer que pour un bit X donné, l’opération X ⊕ 1 a pour résultat l’inverse de X et l’opération X ⊕ 0 a pour résultat X.
Si X représente un jeton, alors X ⊕ 1 le retourne et X ⊕ 0 le laisse inchangé.
Appliquer un coup à une configuration revient à lister les jetons retournés et les jetons non retournés. On peut donc représenter chaque coup par une liste de bits. Par exemple le coup « ligne 1 » est représenté par la liste [1, 1, 1, 0, 0, 0, 0, 0, 0] et l’appliquer à la configuration 67 revient à calculer [0, 0, 1, 0, 0, 0, 0, 1, 1] ⊕ [1, 1, 1, 0, 0, 0, 0, 0, 0].
La figure 3 illustre les 8 coups possibles de la même manière au moyen du ⊕.

On suppose à disposition le dictionnaire coups_possibles qui énumère chaque coup représenté de la sorte :
1 coups_possibles = {
2 "ligne 1" : [1, 1, 1, 0, 0, 0, 0, 0, 0],
3 "ligne 2" : [0, 0, 0, 1, 1, 1, 0, 0, 0],
4 "ligne 3" : [0, 0, 0, 0, 0, 0, 1, 1, 1],
5 "colonne 1" : [1, 0, 0, 1, 0, 0, 1, 0, 0],
6 "colonne 2" : [0, 1, 0, 0, 1, 0, 0, 1, 0],
7 "colonne 3" : [0, 0, 1, 0, 0, 1, 0, 0, 1],
8 "diagonale 1" : [1, 0, 0, 0, 1, 0, 0, 0, 1],
9 "diagonale 2" : [0, 0, 1, 0, 1, 0, 1, 0, 0]
10 }
On souhaite implémenter une fonction qui prend en paramètre un entier config représentant une configuration et qui renvoie la liste des entiers correspondant à toutes les configurations accessibles en un seul coup.
1 def configurations_suivantes(config):
2 config_bin = ...
3 voisins = []
4 for ... in ...:
5 ... # ligne facultative
6 ... = xor_etendu(..., ...)
7 voisins.append(representant(...))
8 return voisins
Recopier et compléter la fonction configurations_suivantes.
Partie B : graphe des configurations
On constate qu’il semble impossible d’atteindre la victoire depuis la configuration représentée par l’entier 4. On appelle configuration perdante toute configuration pour laquelle il n’existe aucune suite de coups menant à la victoire (c’est-à-dire à tous les jetons côté Recto). Inversement, on appelle configuration gagnante toute configuration qui n’est pas perdante.
La configuration représentée par l’entier 4 est effectivement perdante. Pour s’en convaincre on construit le graphe des configurations du jeu Recto-Verso.
Les sommets de ce graphe sont les différentes configurations possibles et il existe une arête s1 → s2 d’un sommet s1 vers un sommet s2 si et seulement s’il est possible de passer de la configuration s1 à la configuration s2 en jouant un coup autorisé.
Montrer que s’il existe une arête x → y dans le graphe, alors il existe également une arête y → x.
En Python, on choisit de représenter ce graphe par un dictionnaire construit grâce à la fonction configurations_suivantes :
1 graphe = {
2 0 : [...],
3 ...
4 67 : [387, 123, 68, 359, 209, 10, 338, 23],
5 ...
6 }
Une représentation par matrice d’adjacence aurait aussi pu être envisagée. Justifier le choix du dictionnaire en comparant pour les deux structures le nombre d’entiers nécessaires pour stocker en mémoire le graphe des configurations. On pourra laisser ce nombre écrit sous la forme d’une puissance de 2.
La fonction parcours_profondeur ci-dessous implémente un parcours en profondeur d’abord. Elle prend en paramètres la représentation d’un graphe, un entier configuration qui indique le sommet que l’on est en train de visiter, et une liste vus de sommets déjà visités par le parcours. Cette fonction effectue le parcours en rajoutant les sommets visités à la liste vus.
1 def parcours_profondeur(graphe, configuration, vus):
2 vus.append(...)
3 for s in ...:
4 if s not in vus:
5 parcours_profondeur(..., ..., ...)
Recopier et compléter la fonction parcours_profondeur.
En utilisant la fonction parcours_profondeur, écrire en Python une suite d’instructions permettant de vérifier que la configuration représentée par l’entier 4 est bien perdante.
Indiquer et justifier quel parcours de graphe (en largeur ou en profondeur) est le plus approprié pour trouver un chemin partant d’une configuration gagnante et menant à la victoire en un minimum de coups.
Métropole – Bac NSI 2026 – Jour 1 Correction de l'exercice 2
Partie A – Représentation binaire des configurations
1. Nombre de configurations
Chacun des 9 jetons peut être sur 2 faces (Recto ou Verso), indépendamment des autres : il y a 2 × 2 × … × 2 = 2⁹ = 512 configurations.
2. Ligne 1, ligne 2, colonne 2 depuis la figure 1
La figure 1 correspond à la liste [0, 0, 1, 0, 0, 1, 1, 1, 0]. On applique les coups :
| coup | configuration obtenue |
|---|---|
| départ | [0, 0, 1, 0, 0, 1, 1, 1, 0] |
| ligne 1 | [1, 1, 0, 0, 0, 1, 1, 1, 0] |
| ligne 2 | [1, 1, 0, 1, 1, 0, 1, 1, 0] |
| colonne 2 | [1, 0, 0, 1, 0, 0, 1, 0, 0] |
Tous les jetons ne sont pas sur Recto : cette séquence ne mène pas à la victoire.
3. Entier de la figure 1
001001110 en binaire : 0×256 + 0×128 + 1×64 + 0×32 + 0×16 + 1×8 + 1×4 + 1×2 + 0×1 = 64 + 8 + 4 + 2 = 78.
4. Fonction representant
def representant(liste):
n = 0
for bit in liste:
n = 2 * n + bit
return n
5. Fonction xor_etendu
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
6. Fonction configurations_suivantes
def configurations_suivantes(config):
config_bin = binaire(config)
voisins = []
for nom in coups_possibles:
coup = coups_possibles[nom] # ligne facultative
suivante = xor_etendu(config_bin, coup)
voisins.append(representant(suivante))
return voisins
Partie B – Graphe des configurations
7. Arête x → y donc arête y → x
S’il existe une arête x → y, c’est qu’un coup c transforme x en y : y = x ⊕ c. Rejouer le même coup donne y ⊕ c = (x ⊕ c) ⊕ c = x, car c ⊕ c ne contient que des 0 et x ⊕ 0 = x. Jouer c depuis y ramène à x : l’arête y → x existe.
8. Dictionnaire ou matrice d’adjacence
Le graphe a 2⁹ = 512 sommets.
– Une matrice d’adjacence contient 512 × 512 = 2¹⁸ entiers (262 144), presque tous nuls.
– Avec le dictionnaire, chaque sommet a exactement 8 voisins : 512 clés et 512 × 8 = 2¹² valeurs, soit 2⁹ + 2¹² = 4 608 entiers.
Le dictionnaire occupe environ 57 fois moins de mémoire : le graphe est peu dense, ce qui justifie ce choix.
9. Fonction parcours_profondeur
def parcours_profondeur(graphe, configuration, vus):
vus.append(configuration)
for s in graphe[configuration]:
if s not in vus:
parcours_profondeur(graphe, s, vus)
10. La configuration 4 est perdante
vus = []
parcours_profondeur(graphe, 4, vus)
print(511 not in vus) # affiche True
11. Le parcours le plus adapté
Le parcours en largeur : il visite les sommets par distance croissante au départ (1 coup, puis 2 coups, etc.). Le premier chemin trouvé vers 511 est donc le plus court. Le parcours en profondeur trouve un chemin, mais pas forcément le plus court.
▶ Animation : le Recto-Verso et le parcours en largeur
Jouez un coup (il retourne 3 jetons, c’est un XOR avec le masque du coup) ou cliquez sur un jeton pour composer une configuration. « Solution la plus courte » lance un parcours en largeur dans le graphe des 512 configurations et rejoue le chemin trouvé jusqu’à 511.
liste : entier :
Une erreur, un oubli ? Écrivez-moi : frederic.peuriere@lfcl.pt
🔎 Exercices sur des thèmes similaires
-
Nouvelle Calédonie 2023 – jour 2 – exercice 2
programmation Python, récursivité — Difficulté : 🔥🔥🔥🔥🔥 -
Amérique du Nord 2025 – jour 2 – exercice 3
BDD, programmation, récursivité, graphes — Difficulté : 🔥🔥🔥🔥🔥 -
Sujet Zéro 2023 – jour 2 – exercice 2
récursivité — Difficulté : 🔥🔥🔥🔥🔥 -
Polynésie 2023 – jour 2 – exercice 1
arbres binaires de recherche, POO, récursivité — Difficulté : 🔥🔥🔥🔥🔥 -
Centres étrangers 2024 – jour 2 – exercice 1
programmation, POO, récursivité — Difficulté : 🔥🔥🔥🔥🔥 -
Centres étrangers 2024 – jour 2 – exercice 2
POO, récursivité, arbres binaires, systèmes d'exploitation — Difficulté : 🔥🔥🔥🔥🔥