Agrégation informatique externe 2025, épreuve 2Sujet et rapport du jury
Agrégation externe section informatique - Sujet de la seconde épreuve écrite de la session 2025
- Analyse de complexité, complexité amortie
- Arbres et preuves par récurrence
- Terminaison et correction d'algorithmes
- Algorithmes gloutons
- Recherche dans les jeux : minimax et élagage alpha-beta
- Programmation en Python, OCaml et C
- Représentation des entiers, schéma de Horner
Téléchargements
- Corrigé : pas encore disponible
Présentation du sujet
DifficileStratégies pour le jeu du Mastermind : arbres de stratégie, glouton, élagage alpha-beta et symétriesAfficher ou masquer la section
Présentation du sujet
DifficileL'épreuve 2 (étude d'un problème informatique) porte sur la recherche de stratégies pour le Mastermind. Elle part de fonctions simples en Python avec analyse de complexité, formalise ensuite les arbres de stratégie et les stratégies optimales avec preuves et code OCaml, puis étudie trois accélérations (pré-calcul en C, stratégie gloutonne, élagage alpha-beta). Une dernière partie exploite les symétries pour réduire l'espace de recherche.
- 1Partie 1 : le jeu et premières fonctionsProgrammation en Python de fonctions simples sur les combinaisons et analyse de leur complexité, dont une complexité amortie.
- 2Partie 2 : arbres de stratégie et stratégies optimalesDéfinition formelle des arbres de stratégie, preuves par récurrence, optimalité et programmation en OCaml.
- 3Partie 3 : accélérer la recherchePré-calcul des similarités entre combinaisons en C, stratégie gloutonne non optimale étudiée et programmée en OCaml, analyse d'un pseudo-code d'élagage alpha-beta.
- 4Partie 4 : exploitation des symétriesRéduction de l'espace de recherche par symétries, avec programmation en OCaml ; partie peu abordée.
Difficile. La moyenne est de 6.99 sur 20, la moitié des présents ont moins de 6.29, et la dernière partie a été peu abordée.
L'épreuve en chiffres
Moyenne 6,99 / 20 · écart-type 5,02 · 125 copies · où vous situez-vous ?Afficher ou masquer la section
L'épreuve en chiffres
- Moyenne
- 6,99/ 20
- Écart-type
- 5,02
- Copies
- 125
- 1er quartile
- 2,83
- Médiane
- 6,29
- 3e quartile
- 10
Votre note sur 20 à ce sujet, en conditions de concours.
Source : rapport du jury. Notes publiées par le concours (après harmonisation le cas échéant). Courbe : estimation par une loi normale.
Ce qu'a observé le jury
6 erreurs relevéesErreurs algorithmiques et réponses trop compliquées · Complexité et preuves peu rigoureuses · Terminaison et récurrences négligéesAfficher ou masquer la section
Ce qu'a observé le jury
6 erreurs relevéesLe jury attend des futures enseignantes des copies claires et un code lisible appliquant les bonnes pratiques qu'elles auront à enseigner. Il déplore de nombreuses erreurs algorithmiques, des erreurs propres à chaque langage et des preuves peu rigoureuses. Le sujet contenait deux erreurs, dans la légende de la figure 2 et dans la question 29.
Les erreurs les plus sanctionnées
- 1Erreurs algorithmiques et réponses trop compliquéesQ2 à Q5
Les réponses aux questions 2 et 3 sont souvent trop compliquées, donc fausses. En question 4, une fonction renvoie vrai dès la première vérification réussie.
« Les correctrices déplorent les nombreuses erreurs algorithmiques trouvées dans les copies. »
- 2Complexité et preuves peu rigoureusesQ7, Q9, Q11
La complexité amortie est identifiée sans démonstration rigoureuse, et certaines réponses alignent des mots-clés sans raisonnement.
« On s’attendait ici à une preuve soignée, par récurrence. »
- 3Terminaison et récurrences négligéesQ17, Q18, Q21
Beaucoup sautent la preuve de terminaison ou n'annoncent pas la récurrence. Certaines copies partent d'une somme fausse et retrouvent le résultat demandé.
« Un certain nombre de copies partent d’une somme fausse et arrivent miraculeusement au résultat demandé. »
- 4Méconnaissance du langage CQ22, Q23
L'opérateur ^ ne calcule pas une puissance, pow travaille sur des double, aucune fonction ne donne la taille d'un tableau et des types inexistants sont inventés. Le schéma de Horner est rarement connu.
« Une fonction ne doit pas renvoyer un pointeur vers un objet qu’elle a alloué sur la pile. »
- 5Mauvais usages d'OCaml et de Python
En OCaml, un filtrage sur une variable existante n'équivaut pas à un test d'égalité. En Python, supprimer des éléments d'une liste pendant son parcours provoque des accès hors bornes.
- 6Affirmations sans démonstrationQ28, Q33 à Q39
Les affirmations ne sont pas justifiées, et l'élagage alpha-beta, pourtant au programme, semble découvert le jour de l'épreuve.
« L’écrasante majorité des copies ne cherche pas à justifier son affirmation par une démonstration. »
Ce qui a été bien réussi
- Beaucoup de copies identifient correctement une notion de complexité amortie en question 7.
- Un bon nombre de copies trouvent un arbre optimal en question 11.
- Quelques copies ont parfaitement traité la question 13, jugée délicate.
- Certaines candidates ont fait un lien pertinent entre élagage alpha-beta et branch-and-bound.
Conseils du jury
- Écrire un code clair : noms de variables explicites, bonne décomposition, peu d'imbrications.
- Réutiliser les questions précédentes et les fonctions standard comme min et max.
- Nommer les fonctions internes plutôt qu'imbriquer des fonctions d'ordre supérieur comme List.fold_left.
- Être précis sur les parties élémentaires plutôt que bâcler le début pour avancer.
- Indiquer lisiblement le numéro de chaque question et ne pas écrire hors du cadre ou en pied de page.
Synthèse rédigée par WikiPrépa à partir du rapport officiel du jury (à télécharger en PDF). Les citations sont extraites du rapport.
Description
Sujet officiel Agrégation externe en informatique, session 2025.
Ces sujets peuvent vous intéresser
Pas encore de corrigé pour ce sujet : voici des sujets proches corrigés.
Lecture du sujet en ligne
L'énoncé complet, avec les formules et les figures, sans ouvrir le PDF.Afficher ou masquer la section
Lecture du sujet en ligne
Egalité
Fraternité
AGREGATION CONCOURS EXTERNE
INFORMATION AUX CANDIDATS

Mastermind
Préliminaires
- -List.map : ('a -> 'b) -> 'a list -> 'b list List.map f [x1; ...; xn] renvoie [f x1; ...; f xn];
- -List.iter : ('a -> unit) -> 'a list -> unit List.iter f [x1; ...; xn] équivaut à f x1; ...; f xn; ();
- -List.fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a List.fold_left f init [x1; ...; xn] renvoie f (... (f (f init x1) x2) ...);
- -List.filter : ('a -> bool) -> 'a list -> 'a list List.filter pred u renvoie la liste constituée des éléments x de u tels que pred x = true, dans l'ordre de la liste u.
- -('a, 'b) Hashtbl.t est le type d'une table de hachage dont les clés sont de type 'a et les valeurs de type 'b;
- -Hashtbl.create : int -> ('a, 'b) Hashtbl.t
Hashtbl.create 1 renvoie une table de hachage vide (l'argument entier est une indication sur la taille initiale du tableau sous-jacent et pourra systématiquement être pris égal à 1); - -Hahstbl.find_opt : ('a, 'b) Hashtbl.t -> 'a -> 'b option
Hahstbl.find_opt h x renvoie Some y si y est la valeur associée à la clé x dans h, ou None si la clé x n'est pas présente dans h ; - -Hashtbl.replace : ('a, 'b) Hashtbl.t -> 'a -> 'b -> unit
Hashtbl.replace h x y associe la clé x à la valeur y dans la table h, en remplaçant l'ancienne association pour x s'il y en avait une (et en créant l'association dans le cas contraire); - -Hashtbl.iter : ('a -> 'b -> unit) -> ('a, 'b) Hashtbl.t -> unit
Hashtbl.iter f h équivaut à f x1 y1; ... ; f xn yn; (), où(x_1, y_1), …, (x_n, y_n) sont les associations présentes dans la table h , dans un ordre non spécifié.
Présentation informelle du jeu
- -
J_1 propose une combinaisonc : par exemple,c = (V, B, V, R, B) ; - -l'arbitre répond à
J_1 en indiquant le nombre de jetons bien placés et mal placés dans sa combinaison ; - -ici, il y a un V bien placé :
| R | R | V | B | R |
| V | B | V | R | B |
- -pour déterminer le nombre de jetons mal placés, on commence par éliminer les jetons bien placés puis l'on oublie l'ordre - ici, il y a deux jetons mal placés (un R et un B);
| R | R R | B |
|
||
| R | B |
- -si l'arbitre répond que tous les jetons sont bien placés (réponse
(N, 0) ), la partie s'arrête ; - -sinon,
J_1 fait une nouvelle proposition et l'on continue.
Formalisation
- -On se donne deux entiers strictement positifs
N etP - dans la version standard du jeu, on aN = 4 etP = 6 . - -On appelle combinaison un
N -uplet d'éléments de{0, …, P − 1} . Attention, il s'agit bien d'unN -uplet et non d'une combinaison au sens usuel en mathématiques : l'ordre compte et les répétitions sont autorisées. - -On notera
C (ouC(N, P) s'il y a risque d'ambiguïté) l'ensemble de ces combinaisons :C = {0, …, P − 1}^N . On a donc|C| = P^N . - -On appellera couleurs les éléments de
{0, …, P − 1} et jetons les éléments duN -uplet. - -Étant données deux combinaisons
x = (x_0, …, x_(N − 1)) ety = (y_0, …, y_(N − 1)) , la similaritésim(x, y) entrex ety est le couple d'entiers(b, m) où :- -
b est le nombre de jetons bien placés dey (par rapport àx ), c'est-à-dire le nombre d'indicesi ∈ {0, …, N − 1} tels quex_i = y_i ; - -
m est le nombre de jetons mal placés dey (par rapport àx ). Ce nombre est tel queb + m soit égal au nombre de jetons en commun entrex ety si l'on ne tient pas compte de l'ordre.
- -
- -Quelques exemples :
- -
sim((2, 3, 0, 2, 3), (3, 3, 3, 1, 2)) = (1, 2) - en effet, il y a au total trois éléments communs (un « 2 » et deux « 3 »), dont l'un est bien placé (le « 3 » à l'indice 1, c'est-à-dire en deuxième position); - -
sim((1, 2, 3), (2, 2, 2)) = (1, 0) (un seul élément commun, le « 2 » à l'indice 1 qui est bien placé); - -
sim((1, 2, 3, 1, 4), (2, 4, 3, 1, 1)) = (2, 3) (à l'ordre près, tous les éléments sont communs, et deux d'entre eux sont bien placés).
- -
- -De manière immédiate, on a
x = y si et seulement sisim(x, y) = (N, 0) . On remarque de plus que sim est symétrique.
- -
sim((2, 1, 3, 4), (1, 2, 3, 4)) ; - -
sim((0, 0, 1, 1), (1, 1, 3, 0)) ; - -
sim((0, 3, 3, 2, 3), (3, 0, 3, 4, 4)) .
Notations et définitions supplémentaires
- -On note
R l'ensemble des similarités (ou réponses) possibles :
R = {sim(x, y)|x, y ∈ C}. - -Pour
X ⊆ C etc ∈ C , on note
sim(X, c) = {sim(x, c)|x ∈ X}. - -Pour
X ⊆ C etc ∈ C etr ∈ R , on note
filtre(X, c, r) = {x ∈ X|sim(c, x) = r}.
- -Pour une liste (éventuellement vide)
h = [(c_1, r_1), …, (c_k, r_k)] (appelée historique) de couples (combinaison, similarité), on définit l'ensemble des combinaisons compatibles avech par
compat(h) = {x ∈ C|∀i ∈ {1, …, k}, sim(x, c_i) = r_i}. - -Un tel historique est dit admissible si
compat(h) ≠ ∅ et si lesr_i avec1 ≤ i < k sont différents de(N, 0) . - -Un historique admissible est dit inachevé si
k = 0 (l'historique est vide) our_k ≠ (N, 0) .
- -une combinaison but
∈ C est choisie par l'arbitre et gardée secrète; - -le joueur
J_1 doit deviner cette combinaison en un minimum d'essais ; - -pour ce faire, il propose à chaque coup une combinaison
c ∈ C ; - -l'arbitre indique alors au joueur
J_1 la valeur desim(x, but) ; - -si cette valeur est
(N, 0) (c'est-à-dire six = but ), la partie s'arrête ; - -sinon, le joueur
J_1 propose une nouvelle combinaison; - -le score du joueur
J_1 est le nombre total d'essais effectués pour trouver but. Le joueurJ_1 cherche donc à minimiser ce score. Si la partie ne se termine jamais, on considère que ce score est infini.
- -L'arbitre choisit
but = (2, 2, 0) comme combinaison secrète à deviner. - -Le joueur
J_1 joue (0, 0, 0), l'arbitre répondsim((0, 0, 0), but) = (1, 0) . - -Le joueur
J_1 joue (0, 1, 2), l'arbitre répondsim((0, 1, 2), but) = (0, 2) . - -Le joueur
J_1 joue (2, 2, 0 ), l'arbitre répond(3, 0) et la partie se termine. Le score de la partie vaut 3.
Partie I. Programmation des fonctions élémentaires
- -une combinaison par une list de longueur N à valeurs dans
{0, …, P − 1} ; - -une réponse par un couple (b, m) d'entiers.
I. 1 Calcul de la similarité
I. 2 Stratégie naïve
[([0, 0, 0], (0, 0)), ([1, 1, 1], (1, 0)), ([1, 2, 2], (0, 1)),
([3, 1, 3], (1, 2)), ([3, 3, 1], (3, 0))]
Partie II. Généralités sur les stratégies
II. 1 Arbre de stratégie
- -en notant
c l'étiquette de la racine, on a un sous-arbre pour chaquer ∈ sim(D, c) (et l'arête reliant la racine à ce sous-arbre est étiquetéer ); - -si
(N, 0) ∈ sim(D, c) , alors le sous-arbre correspondant est une feuille (que l'on étiquettera parfoisc , même si cette étiquette est redondante); - -pour chaque
r ∈ sim(D, c), r ≠ (N, 0) :- -
|filtre(D, c, r)| < |D| ; - -le sous-arbre correspondant à
r est unfiltre(D, c, r) -arbre de stratégie.
- -
- -Si
D = {c} (singleton), alors la combinaison à la racine est nécessairementc (tout autre choix conduirait à violer la condition| filtre(D, c, r)| < |D| ) et l'uniqueD -arbre de stratégie est donc :
Figure 1 - Arbre pour un singleton. - -Pour
N = 3, P = 4 etD = {(1, 2, 2), (3, 3, 1)} , de nombreux arbres sont possibles, dont les deux représentés ci-dessous :
Figure 2 - Deux arbres possibles pourD = {(1, 2, 2), (3, 3, 1)} .On notera en revanche qu'aucunD -arbre ne peut ici avoir de racine étiquetée parc = (0, 0, 0) : pourr = (0, 0) , on auraitfiltre(D, c, r) = D . - -Pour
N = 2 etP = 3 , l'arbre de la figure 3 en page suivante est unC -arbre de stratégie (dans cet arbre, on a noté les couleursa, b, c au lieu de0, 1, 2 pour éviter les confusions entre combinaisons et réponses).

- -On dit qu'un historique
h = ((c_1, r_1), …, (c_k, r_k)) est joué suivant l'arbreT s'il existe un chemin partant de la racine et étiquetéc_1, r_1, c_2, …, c_k, r_k (en alternant étiquette des nœuds internes et étiquettes des arêtes). Notons que s'il existe, ce chemin est unique. - -Pour un
D -arbre de stratégieT et une combinaisonx ∈ D , il existe une unique feuille deT étiquetéex , et donc un unique chemin de la racine à cette feuille. L'historique associé à ce chemin (qui se termine par(x, (N, 0)) ) est appelé partie jouée suivantT pour le butx . - -On note alors
score(T, x) le score de cette partie.
- -la racine lui indique le premier coup à jouer;
- -il reçoit une réponse
r et il sait maintenant que le but est dansfiltre(D, c, r) ; - -il descend dans le sous-arbre correspondant, qui est soit une feuille (si
r = (N, 0) , et la partie est alors terminée), soit unfiltre(D, c, r) -arbre qui lui indiquera comment jouer la suite de la partie.
- -le joueur
J_1 joue (a, b ) (le coup à la racine); - -comme
sim((a, b), but) = (0, 1) , l'arbitre répond(0, 1) et l'on descend dans la branche correspondante; - -
J_1 joue ensuite(b, c) ; - -l'arbitre répond
sim((b, c), but) = (0, 1) , on descend dans cette branche ; - -
J_1 joue(c, a) , l'arbitre répond(2, 0) et l'on descend dans cette branche; - -on arrive sur une feuille, ce qui indique que la partie est terminée.
II. 2 Stratégie optimale
- -Le score dans le pire cas
pire_D(T) d'unD -arbre de stratégieT est défini par :
pire_D(T) = max_(x ∈ D)score(T, x). - -Le poids total poids
_D(T) d'unD -arbre de stratégieT est défini par :
poids_D(T) = ∑_(x ∈ D)score(T, x). - -On définit :
pire_(opt)(D), = min{pire_D(T)|T ∈ T_D}; poids_(opt)(D), = min{poids_D(T)|T ∈ T_D} - -Un
D -arbre de stratégie est dit optimal dans le pire cas s'il vérifie pire_D(s) = pire_(opt)(D) , optimal en moyenne s'il vérifiepoids_D(s) = poids_(opt)(D) .
Question 13. Un arbre est dit optimiste si chaque nœud interne a un enfant feuille. On note
II. 3 Jeu à deux joueurs
- -Le joueur
J_1 choisit librementc_k ∈ C ; - -le joueur
J_2 choisit une réponser_k ∈ sim(compat(h), c_k) ; - -si
r_k = (N, 0) , la partie se termine avec un score final dek , sinon on remplaceh parh, (c_k, r_k) et l'on passe au tour suivant.
II. 4 Représentation informatique
val sim : combi -> combi -> reponse
type strat =
| Gagne
| Noeud of combi * ((reponse * strat) list)
val joue_un_joueur : strat -> combi -> int
val pire : strat -> int
val poids : strat -> int
II. 5 Calcul naïf de pire
_(opt)(D) et poids
_(opt)(D)
Question 17. Pour
Question 18. Donner (sans justification) une définition similaire pour poids
On suppose que l'on dispose d'une fonction reponses_possibles prenant en entrée un ensemble
val reponses_possibles : combi list -> combi -> reponse list
val pire_opt_naif : combi list -> int
val strategie_poids_naive : combi list -> strat
Partie III. Recherche efficace de stratégies
III. 1 Premières optimisations
- -une pour un type combi_int_t permettant de représenter un entier de
{0, …, |C| − 1} ; - -l'autre pour un type rep_int_t permettant de représenter un entier de
{0, …, |R| − 1} .
struct rep_couple_t {
int bien;
int mal;
};
typedef struct rep_couple_t rep_couple_t;
const int N = 4; // valeur purement indicative
const int P = 6; // idem
const int NB_COMBIS = ...; //
rep_couple_t similarite(int x[], int y[]);
rep_int_t rep_int_of_rep_couple(rep_couple_t couple);
La fonction rep_int_of_rep_couple prend un couple
combi_int_t int_of_combi(int x[]);
int *combi_of_int(combi_int_t x);
rep_int_t sim(combi_int_t x, combi_int_t y);
type combi = int
type reponse = int
- -On suppose de plus disposer de deux constantes globales nb_combis et nb_reponses correspondant respectivement à
|C| et|R| . - -Les combinaisons sont numérotées de 0 à nb_combis - 1 et les réponses de 0 à nb_reponses - 1. On suppose de plus que la constante tous_bons, de type reponse, correspond au codage de la réponse
(N, 0) . - -La constante toutes_combis est toujours disponible, et de type combi list.
- -La fonction sim est toujours disponible (et utilise les nouveaux types) mais s'exécute à présent en temps constant.
III. 2 Stratégie gloutonne
- -les liste
u_i sont non vides et disjointes; - -l'union des éléments des listes
u_i vautX∖{c} ; - -pour chaque
u_i , il exister_i ≠ (N, 0) tel quev_i = filtre(X, c, r_i) .
val repartit : combi list -> combi -> combi list list
val choix_glouton : combi list -> combi list -> combi
III. 3 Majorations et minorations
Algorithme
1αβ .
fonction Eval1 (buts,
α, β )
si
| buts
|=1 alors
renvoyer 1
h_(min) ← β
pour
c ∈ split(X) faire
h ← Eval2( buts
, c, α − 1, h_(min) − 1)
h_(min) ← min(h + 1, h_(min))
si
h_(min) ≤ α alors
renvoyer
h_(min)
renvoyer
h_(min)
fonction Eval2(buts,
c, α, β )
repartition
= {(r , filtre
( buts
, c, r))|r ∈ sim( buts,
c)}
h_(max) ← α
pour
(r , buts
^′) ∈ repartition faire
si
r ≠ (N, 0) alors
h ← Eval1
( buts
^′, h_(max), β)
h_(max) ← max(h_(max), h)
si
h_(max) ≥ β alors
renvoyer
h_(max)
renvoyer
h_(max)
Partie IV. Prise en compte des symétries
IV. 1 Définitions et premières propriétés
- -On appelle permutation des positions une permutation
σ de l'ensemble{0, …, N − 1} des positions. - -On appelle permutation des couleurs une permutation
τ de l'ensemble{0, …, P − 1} des couleurs. - -On dit qu'une application
α deC dansC est une transformation s'il existe une permutation des positionsσ et une permutation des couleursτ telles que :
∀x ∈ C, α(x) = (τ(x_(σ(0))), …, τ(x_(σ(N − 1)))).
On note alorsα = (σ, τ) . - -On note
S l'ensemble des transformations.
- -
α est une bijection, etα^(− 1) ∈ S ; -
− α ∘ β ∈ S .
IV. 2 Implémentation
son
val applique : transfo -> combi -> combi
val toutes_transfos : transfo list
IV. 3 Équivalence de coups
- (i)
Id_C ∈ T ; - (ii)si
α, β ∈ T , alorsα ∘ β ∈ T ; - (iii)si
α ∈ T , alorsα^(− 1) ∈ T .
Question 42. Montrer que si
Pour une combinaison
- -
[x]_T la classe d'équivalence dex modulo la relation∼ _T ; - -
repr_T(x) le plus petit élément de[x]_S pour l'ordre lexicographique (qu'on appelle représentant dex modulo∼ _T ).
Question 43. Écrire une fonction coups_canoniques prenant en entrée un ensemble
val coups_canoniques : transfo list -> combi list
IV. 4 Extension aux coups suivants
val fix : combi list -> transfo list
Question 48. En déduire une modification des fonctions Eval1 et/ou Eval2 permettant de restreindre les coups à considérer.
Questions fréquentes
4 questionsSur quoi portait l'épreuve 2 de l'agrégation externe d'informatique 2025 ?Afficher ou masquer la section
Questions fréquentes
4 questionsSur quoi portait l'épreuve 2 de l'agrégation externe d'informatique 2025 ?
Sur la recherche de stratégies pour le Mastermind : arbres de stratégie, stratégies optimales, stratégie gloutonne, élagage alpha-beta et symétries, avec du code en Python, OCaml et C.
Quelle est la moyenne de l'épreuve 2 de l'agrégation d'informatique 2025 ?
La moyenne est de 6.99 sur 20 avec un écart-type de 5.02, pour 125 présents. La meilleure note est 20.
Quelles erreurs le jury de l'agrégation d'informatique 2025 a-t-il relevées à l'épreuve Mastermind ?
De nombreuses erreurs algorithmiques, des preuves de complexité ou de terminaison peu rigoureuses, des erreurs de base en C et des affirmations non démontrées.
Quels langages faut-il maîtriser pour l'écrit de l'agrégation d'informatique 2025 ?
L'épreuve Mastermind demandait du code en Python, en OCaml et en C. Le jury attend un code lisible respectant les bonnes pratiques de chaque langage.
Pas de description pour le moment