Exercice 2 Centres étrangers – Bac NSI 2025 – Jour 1
mots clés: algorithmique, récursivité, files
🔎 Voir les exercices similaires ↓
Centres étrangers – Bac NSI 2025 – Jour 1 Énoncé de l'exercice 2
Cet exercice porte sur l’algorithmique, la récursivité et les files.
On cherche à implémenter en Python le jeu de cartes soupe de nombres créé par Javier Dominguez Cruz et paru aux éditions EDGE.
Il s’agit d’un jeu de calcul mental où les joueurs doivent réaliser un nombre à l’aide d’une succession d’opérations mathématiques élémentaires : addition, soustraction, multiplication et division. Par souci de simplification, dans tout cet exercice, la seule opération utilisée sera l’addition.
Tout d’abord, on dispose d’un jeu de cartes sur lesquelles est inscrit un nombre. On sélectionne aléatoirement 12 cartes que l’on dispose sous la forme d’une grille de 3 lignes et 4 colonnes. Dans la suite, une telle grille sera appelée plateau de jeu. Ensuite, plusieurs manches sont jouées en choisissant un nombre cible aléatoire.
Un exemple de manche est présenté dans le schéma suivant.

L’objectif est de trouver une plus courte chaîne valide (celle dont le nombre de cartes est le plus petit possible) dont la somme vaut la cible (cette chaine peut être constituée d’un seul nombre). Pour constituer une chaine, deux cartes consécutives de cette chaîne doivent être voisines dans la grille, horizontalement, verticalement ou diagonalement. Une même carte ne peut pas être utilisée plusieurs fois dans une chaine.
Avec le plateau ci-dessus, on peut obtenir le nombre 27 de plusieurs manières. Le schéma suivant présente trois exemples de chaînes pour obtenir 27. Les deux premières, de longueur 3, sont les plus courtes possibles.

On remarque que les enchainements suivants ne sont pas des chaines :
12+15 car les cartes ne sont pas voisines ;
9+9+8 car la carte contenant le nombre 9 est utilisée plusieurs fois.
Afin d’implémenter ce jeu en Python, on représente le plateau de nombres par la liste de ses lignes, chacune d’entre elles étant représentée par une liste d’entiers. Ainsi, le plateau précédent sera représenté par :
plateau = [
[ 6, 7, 11, 6],
[ 8, 14, 6, 7],
[12, 9, 8, 15]
]
Le but est de proposer un code qui simule le jeu et propose une des meilleures solutions. On va considérer une extension des règles précédentes où les plateaux sont de taille quelconque. Soit le code Python suivant :
v = plateau[1][2]
Donner la valeur de v obtenue.
On souhaite écrire une fonction plateau_init telle que plateau_init(n, m, cartes) où :
n et m sont deux entiers naturels non nuls et
cartes est une liste d’au moins n × m entiers,
renvoie un plateau à n lignes et m colonnes comportant des nombres choisis au hasard parmi cartes sans remise.
La fonction shuffle du module random mélange aléatoirement une liste en la modifiant en place.
Compléter le programme suivant :
def plateau_init(n, m, cartes): shuffle(cartes) plateau = ... for i i... ra...ge(...): plateau.append([cartes[i+j*n] for j in range(m)]) return ...Compléter la fonction cartes_voisines telle que cartes_voisines(n, m, i, j), où (i, j) sont les coordonnées d’une carte dans un plateau à n lignes et m colonnes, renvoie la liste des coordonnées des cartes voisines de (i, j).
def cartes_voisines(n, m, i, j):
voisines = []
for i2 in range(i-1, i+2):
for j2 in ...:
if (i2, j2) != (i, j) and \
i2 in range(n) and \
...:
voisines.append( ... )
return ...
On va représenter une chaîne comme une liste de coordonnées des cartes correspondantes. Ainsi, la chaîne 6+7+6+8 présente dans le schéma précédent sera représentée par la liste Python suivante :
chaine = [ (0,0), (0,1), (1,2), (2,2) ]
Soit l’enchainement suivant :
e1 = [ (2,1), (1,0), (0,0), (0,1) ]
e2 = [ (1,1), (1,2), (2,0) ]
e3 = [ (0,2), (0,3), (1,4) ]
Donner la valeur associée à e1, e2 et e3 (si la chaine existe)
Écrire une fonction chaine_evalue qui prend en paramètres un plateau et une chaine, et renvoie la valeur associée à une telle chaîne.
Avec la chaine précédente, chaine_evalue(plateau, chaine) renverra l’entier 27.
Pour réaliser l’exploration et obtenir une chaine la plus courte possible, on va considérer un parcours en largeur depuis chaque carte du plateau.
Expliquer pourquoi il est pertinent d’utiliser un parcours en largeur plutôt qu’un parcours en profondeur pour réaliser l’exploration permettant d’obtenir une chaine la plus courte possible.
Afin de réaliser ce parcours, on suppose définie une structure de donnée file munie des quatre opérations suivantes :
file_init telle que file_init() renvoie une nouvelle file vide ;
file_ajoute telle que file_ajoute(f, x) ajoute x dans la file f ;
file_retire telle que file_retire(f) retire l’élément de f le plus anciennement ajouté, si la file est vide l’exception ValueError sera émise ;
file_est_vide telle que file_est_vide(f) renvoie un booléen indiquant si la file f est vide.
Recopier et compléter les lignes incomplètes de la fonction explore qui réalise le parcours.
def explore(plateau, cible):
n, m = len(plateau), len(plateau[0])
a_visiter = ... # ligne 3
for i in range(n):
for j in range(m):
file_ajoute(a_visiter, [(i,j)])
while ...: # ligne 8
chemin = file_retire(a_visiter)
if chaine_evalue(plateau, chemin) == ...: # ligne 10
return chemin
dernier = chemin[-1]
i0, j0 = dernier
for i, j in cartes_voisines(n, m, i0, j0):
if (i, j) not in ...: # ligne 15
file_ajoute(a_visiter,
chemin + [ (i,j) ])
# Pas de solutions
return None
Expliquer, sans écrire de code mais en décrivant votre solution, comment modifier la fonction explore afin qu’elle renvoie la liste de tous les chemins solutions.
Centres étrangers – Bac NSI 2025 – Jour 1 Correction de l'exercice 2
Question 1
Réponse : 6
Question 2
def plateau_init(n, m, cartes):
shuffle(cartes)
plateau = []
for i in range(n):
plateau.append([cartes[i+j*n] for j in range(m)])
return plateau
Question 3
def cartes_voisines(n, m, i, j):
voisines = []
for i2 in range(i-1, i+2):
for j2 in range(j-1, j+2):
if (i2, j2) != (i, j) and \
i2 in range(n) and \
j2 in range(m):
voisines.append((i2, j2))
return voisines
Question 4
e1 : 9 + 8 + 6 + 7 = 30 (cartes bien voisines deux à deux).
e2 : ce n’est pas une chaîne : (1,2) et (2,0) ne sont pas voisines.
e3 : n’existe pas : (1,4) est hors du plateau (les colonnes vont de 0 à 3).
Question 5
def chaine_evalue(plateau, chaine):
s = 0
for i, j in chaine:
s = s + plateau[i][j]
return s
Question 6
Le parcours en largeur explore d’abord les chemins les plus courts.
Question 7
def explore(plateau, cible):
n, m = len(plateau), len(plateau[0])
a_visiter = file_init()
for i in range(n):
for j in range(m):
file_ajoute(a_visiter, [(i,j)])
while not file_est_vide(a_visiter):
chemin = file_retire(a_visiter)
if chaine_evalue(plateau, chemin) == cible:
return chemin
dernier = chemin[-1]
i0, j0 = dernier
for i, j in cartes_voisines(n, m, i0, j0):
if (i, j) not in chemin:
file_ajoute(a_visiter,
chemin + [ (i,j) ])
# Pas de solutions
return None
Question 8
Au lieu de retourner le premier chemin trouvé, il faut stocker tous les chemins valides dans une liste et continuer l’exploration.
On crée une liste vide solutions au début ; on remplace return chemin par solutions.append(chemin) et on continue le parcours ; à la fin, on renvoie solutions au lieu de None.
Une erreur, un oubli ? Écrivez-moi : frederic.peuriere@lfcl.pt
🔎 Exercices sur des thèmes similaires
-
Nouvelle Caldédonie 2023 – jour 2 – exercice 2
programmation Python, récursivité — Difficulté : 🔥🔥🔥🔥🔥 -
Métropole 2025 – jour 1 – exercice 2
algorithmique, structures de données, processus — Difficulté : 🔥🔥🔥🔥🔥 -
Centres étrangers 2024 – jour 2 – exercice 2
POO, récursivité, arbres binaires, systèmes d'exploitation — Difficulté : 🔥🔥🔥🔥🔥 -
Centres étrangers 2024 – jour 2 – exercice 1
programmation, POO, récursivité — Difficulté : 🔥🔥🔥🔥🔥 -
Asie 2024 – jour 1 – exercice 1
programmation, POO, algorithmique — Difficulté : 🔥🔥🔥🔥🔥 -
Sujet Zéro 2024 – jour 2 – exercice 2
systèmes d'exploitation, commandes UNIX, piles, files, processus — Difficulté : 🔥🔥🔥🔥🔥