Centrale Option Informatique MP 2018Sujet, corrigé et rapport du jury
- Structures de données Caml : vecteurs, listes, types construits
- Recherche dichotomique et complexité logarithmique
- Tri par insertion et analyse de complexité
- Implantation d’une file par deux listes
- Tables de hachage, facteur de remplissage, tables dynamiques
- Parcours en largeur d’un graphe (BFS) et complexité
Téléchargements
Présentation du sujet
Résolution algorithmique du jeu Ricochet RobotsAfficher ou masquer la section
Présentation du sujet
Le sujet propose de programmer en Caml une résolution du jeu de plateau « Ricochet Robots » : déplacement d’un robot dans une grille avec obstacles, fonctions utilitaires (tri, listes, structure de file), tables de hachage, puis résolution du jeu par un parcours en largeur d’un graphe dont les sommets sont les configurations de robots. Les quatre parties sont relativement indépendantes.
- 1I. Déplacement d’un robot dans une grilleOn écrit une dichotomie, puis les fonctions calculant les déplacements possibles d’un robot dans une grille avec obstacles, en tenant compte des autres robots, et on évalue la complexité d’une résolution naïve par force brute.
- 2II. Quelques fonctions utilitairesOn écrit un tri par insertion, des fonctions sur les listes de couples, puis une structure de file implantée à l’aide de deux listes.
- 3III. Tables de hachageOn construit une structure de dictionnaire par table de hachage, on étudie la complexité moyenne de la recherche sous hypothèse de hachage uniforme, puis on l’étend à des tables de hachage dynamiques à largeur variable.
- 4IV. Résolution du jeu des robotsOn modélise le jeu par un graphe orienté dont les sommets sont les configurations de robots, et on démontre puis implante un parcours en largeur donnant le nombre minimal de déplacements, en remplaçant les tableaux par un dictionnaire à table de hachage dynamique.
L'épreuve en chiffres
Moyenne 10,29 / 20 · écart-type 3,61 · 1 573 présents · où vous situez-vous ?Afficher ou masquer la section
L'épreuve en chiffres
- Moyenne
- 10,29/ 20
- Écart-type
- 3,61
- Présents
- 1 573
- Durée
- 4 h
- 1er quartile
- 7,5
- Médiane
- 10,3
- 3e quartile
- 12,9
Votre note sur 20 à ce sujet, en conditions de concours.
Source : document officiel du concours. 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éesSignatures Caml non respectées · Filtrage mal utilisé · Fonctions auxiliaires multipliées inutilementAfficher ou masquer la section
Ce qu'a observé le jury
6 erreurs relevéesLe sujet a été globalement compris, les meilleurs candidats ayant pu le traiter en entier, tandis que d’autres copies restent très faibles, parfois même non rédigées en Caml. Le jury regrette des critiques qui reviennent d’année en année : signatures Caml non respectées, syntaxe peu respectée, mauvaise compréhension des références ou du filtrage, et analyse de complexité rarement justifiée.
Les erreurs les plus sanctionnées
- 1Signatures Caml non respectées
Les signatures des fonctions demandées étaient imposées par l’énoncé et les réponses doivent impérativement y correspondre.
« Les signatures des fonctions Caml étaient imposées, les réponses doivent correspondre. »
- 2Filtrage mal utilisé
Certains candidats filtrent sur le nom de la variable cherchée plutôt que de tester la valeur de l’expression filtrée.
« Le filtrage est mal utilisé, certains candidats filtrent sur le nom de la variable cherchée au lieu de tester la valeur de l’expression filtrée. »
- 3Fonctions auxiliaires multipliées inutilement
De nombreux candidats réécrivent plusieurs fois les mêmes fonctions ou multiplient les fonctions auxiliaires, ce qui complique la lecture du code et fait perdre du temps.
« Beaucoup de candidats réécrivent plusieurs fois les mêmes fonctions, ce qui leur fait perdre du temps et complique la lecture en multipliant les fonctions auxiliaires »
- 4Dichotomie mal maîtriséeQ1, Q6
Écrire correctement une dichotomie reste difficile, et il fallait aussi en tenir compte dans le calcul de complexité de la question 6.
« A binary search program is notoriously hard to get right »
- 5Confusion entre clé et élément
Les principales erreurs de la partie sur les tables de hachage viennent d’une incompréhension de fond de leur intérêt, avec des confusions entre la clé et l’élément associé.
« Il y a alors des confusions entre la clé et l’élément. »
- 6Résultats affirmés sans démonstrationIV
Dans la dernière partie, des éléments sont qualifiés d’« évidents » ou de résultats de cours au lieu d’être démontrés, ce qui ne convainc pas le jury.
« Les démonstrations doivent être complètes et précises à fortiori s’il s’agit d’un résultat du cours. »
Ce qui a été bien réussi
- Une majorité de candidats a traité de façon satisfaisante les fonctions classiques de la deuxième partie.
- L’utilisation des booléens était satisfaisante cette année.
- Beaucoup de candidats ont proposé des présentations agréables, avec changements de page corrects, couleurs, indentations et commentaires pertinents.
Conseils du jury
- Respecter scrupuleusement les signatures de fonctions imposées par l’énoncé.
- Réutiliser les fonctions déjà écrites plutôt que de les reprogrammer ou de multiplier les fonctions auxiliaires.
- Pratiquer la programmation sur machine en amont du concours pour acquérir les bons réflexes.
- Toujours démontrer complètement un résultat, même s’il semble évident ou déjà vu en cours.
- Conserver les notations données par l’énoncé plutôt que d’en introduire de nouvelles.
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.
Ces sujets peuvent vous intéresser
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
Étude du jeu Ricochet Robots
Ce sujet porte sur la résolution de la situation pratique du jeu «Ricochet Robots» (Rasende Roboter pour la première édition en allemand) créé par Alex Randolph en 1999. Ce jeu se déroule sur un plateau de

- copy_vect : 'a vect -> 'a vect telle que l'appel copy_vect v renvoie un nouveau tableau contenant les valeurs contenues dans v;
- make_vect : int -> 'a -> 'a vect telle que l'appel make_vect
n × renvoie un nouveau tableau de longueur n initialisé avec des éléments égaux à x ; - make_matrix : int -> int -> 'a -> 'a vect vect telle que l'appel make_matrix p q x renvoie une nouvelle matrice à p lignes et q colonnes initialisée avec des éléments égaux à x.
I Déplacement d'un robot dans une grille
.jpg)
let obstacles_lignes = [| [|0; 4; 10; 16|]; [|0; 14; 16|]; [|0; 6; 16|];
[|0; 9; 16|]; [|0; 3; 15; 16|]; [|0; 7; 16|]; [|0; 1; 12; 16|]; [|0; 7; 9; 16|];
[|0; 7; 9; 16|]; [|0; 4; 13; 16|]; [|0; 6; 16|]; [|0; 10; 16|]; [|0; 8; 16|];
[|0; 2; 15; 16|]; [|0; 4; 10; 16|]; [|0; 5; 12; 16|] |];;
let obstacles_colonnes = [| [|0; 5; 11; 16|]; [|0; 6; 13; 16|]; [|0; 4; 16|];
[|0; 15; 16|]; [|0; 10; 16|]; [|0; 3; 16|]; [|0; 10; 16|]; [|0; 6; 7; 9; 12; 16|];
[|0; 7; 9; 16|]; [|0; 3; 12; 16|]; [|0; 14; 16|]; [|0; 16|]; [|0; 7; 16|];
[|0; 2; 10; 16|]; [|0; 4; 13; 16|]; [|0; 2; 12; 16|] |];;
Q 1. Écrire une fonction dichotomie a
On considère un robot positionné en

(ouest/est/nord/sud). Si le robot ne peux pas bouger dans une direction donnée (car il est contre un obstacle), on considérera que le résultat du déplacement dans cette direction est la case (
Q 3. Écrire une fonction matrice_deplacements (), de type unit -> (int * int) vect vect vect produisant une matrice m telle que m. (a). (b) contienne le vecteur des déplacements possibles pour un robot depuis la case (
On cherche maintenant à intégrer les positions d'autres robots dans le déplacement d'un robot. On utilise la fonction précédente pour créer une matrice mat_deplacements que l'on considérera comme globale.
Q 4. Écrire une fonction modif
(int * int) vect -> int * int -> int * int -> unit
On s'intéresse maintenant au déplacement d'un robot situé en
Q 5. Déduire des questions précédentes une fonction deplacements_robots (a,b) q de signature
int * int -> (int * int) list -> (int * int) vect
Q 6. Si on suppose que la solution optimale demande au plus
La suite du problème a pour objet de proposer une solution plus efficace pour la résolution du jeu Ricochet Robots.
II Quelques fonctions utilitaires
II.A - Une fonction de tri
Q 8. En déduire une fonction tri_insertion
Q 9. Rappeler la complexité de ce tri dans le pire et le meilleur cas. Que peut-on dire de la complexité si dans la liste q , tous les éléments excepté peut-être un sont dans l'ordre croissant ?
II.B - Quelques fonctions sur les listes
Q 11. Écrire une fonction assoc
II.C - Implantation d'une structure de file
type 'a file = {mutable entree: 'a list; mutable sortie: 'a list};;
On pourra utiliser les fonctions suivantes, qui permettent de manipuler une file ainsi définie :
creer_file_vide : unit -> 'a file crée une file vide
est_vide_file : 'a file -> bool teste si une file est vide
enfiler : 'a file -> 'a -> unit ajoute un élément à une file
defiler: 'a file -> 'a supprime l'élément en tête de file et le renvoie
On pourra supposer dans la suite que ces fonctions sont écrites de sorte que toute suite de
III Tables de hachage
Une structure de dictionnaire est un ensemble de couples (clé, élément), les clés (nécessairement distinctes) appartenant à un même ensemble
- recherche d'un élément connaissant sa clé ;
- ajout d'un couple (clé, élément) ;
- suppression d'un couple connaissant sa clé.
Ainsi pour rechercher ou supprimer l'élément de clé
III.A - Une famille de fonctions
h_w
Q 12. Écrire une fonction récursive hachage_liste w q de signature int
III.B - Tables de hachage de largeur fixée
type ('a, 'b) table_hachage = {
hache: 'a -> int;
donnees: ('a * 'b) list vect;
largeur: int};;
III.B.1) Implantation de la structure de dictionnaire
Q 14. Écrire une fonction recherche
Q 15. Écrire une fonction element
Q 16. Écrire une fonction ajout
Q 17. Écrire enfin une fonction suppression
III.B.2) Étude de la complexité de la recherche d'un élément
peut espérer que les clés vont se répartir de façon apparemment aléatoire dans les alvéoles, ce qui donnera une complexité bien meilleure.
Nous faisons donc ici l'hypothèse de hachage uniforme simple : pour une clé donnée, la probabilité d'être hachée dans l'alvéole
Q 18. On se donne une clé
Q 19. On prend au hasard une clé présente dans la table ; toutes les clés sont équiprobables. Montrer qu'alors la recherche de la clé se fait en
III.C - Tables de hachage dynamique
À une table de hachage dynamique est associée une famille de fonctions de hachage
type ('a,'b) table_dyn = {
hache: int -> 'a -> int;
mutable taille: int;
mutable donnees: ('a * 'b) list vect;
mutable largeur: int};;
- la fonction hache possède un paramètre supplémentaire qui est la largeur de hachage, elle correspond maintenant à la famille de fonctions de hachage (
h_w ); - on a rendu les champs donnees et largeur modifiables;
- un champ taille (modifiable) est rajouté, il doit à tout moment contenir le nombre de clés présentes dans la table.
Q 20. Écrire une fonction creer_table_dyn h permettant de créer une table de hachage dynamique initialement vide, avec la famille de fonctions de hachageh et la largeur initiale 1.
On admet avoir écrit deux fonctions recherche_dyntk et element_dyntk , variantes des fonctions recherche et element précédentes, basées sur le même principe. On va maintenant développer une stratégie pour maintenir à tout moment un facteur de remplissage borné.
Q 21. Écrire une fonction rearrange_dyn t w2 prenant en entrée une table de hachage dynamique et une nouvelle largeur de hachage w2, qui réarrange la table sur une largeur w2. En supposant que le calcul des valeurs de hachage se fasse en temps constant, la complexité doit être enO(n + w + w_2) oùn est le nombre de clés présentes dans la table (sa taille),w est l'ancienne largeur de la table,w_2 la nouvelle.
Une stratégie heuristique simple pour garantir que le facteur de remplissage reste borné, tout en garantissant une bonne répartition des clés dans le cas des listes de couples à valeurs dans[ [0, N − 1] ] avecN = 16 , est d'utiliser les puissances de 3 comme largeurs de hachage. Après ajout d'un élément à la table, si celle-ci est de taille strictement supérieure à trois fois sa largeurw , on la réarrange sur une largeurw^′ = 3w .
Q 22. Écrire une fonction ajout_dyn t k e ajoutant le couple (k, e ) à la table de hachage (si la clék n'est pas présente), en réarrangeant si nécessaire la table, en suivant le principe ci-dessus.
Dans l'hypothèse que chaque ajout se fait en tempsO(1 + α) , oùα est le facteur de remplissage de la table, on peut montrer qu'une série dep ajouts dans une table initialement vide prend un tempsO(p) .
On pourrait écrire de même une fonction de suppression dynamique, de sorte de maintenir un facteur de remplissage de la table borné, et qu'une série dep opérations licites d'insertion/suppression dans la table prenne un tempsO(p) .
IV Résolution du jeu des robots
IV.A - Graphe orienté associé au jeu des robots
type sommet = {robot: int * int; autres_robots: (int * int) list};;
Les arcs dans le graphe (orienté) sont définis naturellement : un sommet
Q 23. Avec
Q 24. Écrire une fonction sommets_accessibles
IV.B - Parcours en largeur : étude théorique
Entrées : un arbre $G=(S, A)$, orienté, un sommet de départ $s_{0}$
Sortie : un tableau de booléens, un tableau de prédecesseurs
$F \leftarrow$ creer_file_vide () ;
Enfiler $s_{0}$ dans $F$;
$b_{s_{0}} \leftarrow$ vrai ;
$b_{s} \leftarrow$ faux pour tout $s \in S$; (* un tableau de booléens pour chaque sommet, tous faux *)
$\pi_{s} \leftarrow s$ pour tout $s \in S$; (* un tableau de prédecesseurs pour chaque sommet, initialement $\pi[s]=s^{*}$ )
tant que $F$ est non vide faire
$s \leftarrow \operatorname{defiler}(F) ;$
pour tout $s^{\prime}$ voisin de $s$ tel que $b_{s^{\prime}}$ est faux faire
$b_{s^{\prime}} \leftarrow$ vrai $; \pi_{s^{\prime}} \leftarrow s$; enfiler $s^{\prime}$ dans $F$;
fin pour
fin tant que
renvoyer $b, \pi$
Algorithme 1 Parcours en largeur
Q 26. Montrer que l'algorithme visite tous les sommets
Q 27. Pour un sommet
Q 28. Montrer que ce chemin est un plus court chemin de
Q 29. On suppose que les voisins sont implantés par liste d'adjacence, la complexité est linéaire en le nombre de voisins pour les parcourir. Les opérations de file et les opérations sur les tableaux
Un parcours en largeur du graphe associé au jeu permet donc de trouver une solution qui nécessite le minimum de déplacements des robots. La difficulté dans l'implantation de cet algorithme réside dans le grand nombre de sommets du graphe. Pour pallier cette difficulté, on remplace les tableaux
Questions fréquentes
4 questionsSur quels chapitres porte le sujet Centrale option informatique MP 2018 ?Afficher ou masquer la section
Questions fréquentes
4 questionsSur quels chapitres porte le sujet Centrale option informatique MP 2018 ?
Le sujet porte sur les vecteurs et listes Caml, la dichotomie, le tri par insertion, les structures de file, les tables de hachage et le parcours en largeur d’un graphe.
Quelles erreurs le jury a-t-il le plus relevées en option informatique Centrale MP 2018 ?
Le rapport cite des signatures de fonctions non respectées, un filtrage mal utilisé, des fonctions auxiliaires inutilement multipliées et des résultats affirmés sans démonstration complète.
Le sujet Centrale option informatique MP 2018 est-il faisable en entier ?
Le rapport indique que les meilleurs candidats ont pu traiter le problème en entier, le texte ayant été choisi d’une longueur raisonnable.
Quel langage de programmation est utilisé dans le sujet Centrale option informatique MP 2018 ?
Le sujet est à traiter en Caml, avec des signatures de fonctions imposées par l’énoncé.
Pas de description pour le moment
