L'objectif de ce travail est de résoudre le problème de $n$ reines : sur un échiquier de taille $n \times n$, peut-on poser $n$ reines de telle sorte qu'aucune reine ne soit menacée par une autre reine ? Connaissant les règles des échecs, il faut donc placer les $n$ reines de sorte qu'il n'y ait jamais deux reines sur la même ligne, ni sur la même colonne, ni sur une même diagonale. Le TP demandera d'écrire plusieurs fonctions récursives sur les listes. Plus tard, nous apprendrons à utiliser les fonctionnelles de listes, et nous pourrons refaire ce TP bien plus simplement.
Chaque position sera encodée sous la forme d'un couple abscisse $\times$ ordonnée. Écrire une fonction independant prenant deux positions en argument, et retournant un booléen, indiquant si deux reines sur ces positions se menacent l'une l'autre.
Le cas des diagonales est le plus compliqué. Souvenez-vous que les lignes obliques du plan ont pour équations $x+y=c$ ou $x-y=c$ avec une constante $c$.
Tester votre fonction sur des exemples.
Répondre aux questions suivantes, sans oublier d'écrire des tests à chaque fois.
Écrire une fonction récursive range pour définir une liste d'entiers consécutifs entre deux bornes. Par exemple :
Écrire une fonction récursive append concaténant deux listes :
Écrire une fonction récursive couple prenant un élément a et une liste [b1; b2; ... bn], et qui s'évalue en la liste [(a,b1);(a,b2);...;(a,bn)]. Par exemple :
Écrire une fonction récursive flatten, prenant une liste de listes d'éléments, et qui s'évalue en la liste union de tous les éléments de ces listes, dans le même ordre.
Écrire une fonction product, prenant deux listes, et s'évaluant en la liste des couples dont le premier terme est choisi dans la première liste, et le second terme est choisi dans la deuxième liste. On écrira d'abord une fonction unflattened_product, qui retourne une liste de listes de couples, à laquelle il suffira d'appliquer flatten.
En déduire la liste des positions :
Nous voulons maintenant écrire la fonction de résolution. Pour cela, nous allons ajouter deux contraintes supplémentaires :
Écrire une fonction récursive solve qui, prenant ces deux listes en arguments, calcule l'ensemble des solutions réalisables. Pour cela :
Créer une fonction pour afficher vos solutions. Vous pouvez utiliser au choix Printf.printf, ou bien la librairie Graphics. Deux solutions affichées avec Printf.printf :
Pour afficher avec la librairie Graphics, écrire une fonction graphic_print_solution prenant une solution en argument, et affichant cette solution, puis utiliser la définition suivante :
Généraliser votre code pour calculer les solutions du problème des $n$-reines, pour n'importe quelle valeur de $n$.