Projet IAP2 - Groupe 2 Mehdi Chouiten - Benoit Robillard Solveur de puzzles un peu particuliers Décembre 2010 1 Le problème Dans ce projet, on se propose de résoudre un puzzle casse-tête , composé uniquement de pièces carrées. Chacune de ces pièces est décomposée en quatre triangles délimités par les diagonales de la pièce. Ces triangles sont colorés soit en bleu, soit en jaune, soit en rouge, soit en vert. La gure 1 donne un exemple de pièce. Fig. 1 Un exemple de pièce de puzzle Le but est, étant donnés les dimensions du puzzle et le jeu de pièces associé, de placer un maximum de pièces, de sorte à ce que deux pièces placées l'une à coté de l'autre se touchent sur des triangles de même couleur. Dans l'idéal, il faut placer toutes les pièces ; en pratique, le problème peut rapidement devenir dicile en raison de l'explosion combinatoire du nombre de possibilités, et l'on tente plutôt de maximiser le nombre de pièces placées. 2 Les briques de base Question 1 Dénir la structure piece des pièces du puzzle. Le bleu sera identié par l'entier 1, le jaune par l'entier 2, le rouge par l'entier 3 et le vert par l'entier 4. Attention, une pièce peut être tournée dans tous les sens. Question 2 Dénir une fonction make_piece qui construit une pièce de puzzle à partir de quatre couleurs. La première couleur se trouvera en bas de la pièce, la deuxième à gauche, la troisième en haut et la quatrième à droite. 1 4 B R J B Fig. 4 J B V J R J R J V J B R 2 Un exemple de chir représentant un puzzle de taille 4x4. Question 3 Dénir une structure puzzle contenant les dimensions du puzzle, les pièces disponibles et une solution courante. Question 4 Écrire une fonction check_solution qui renvoie le nombre de pièces correctement placées, c'est-à-dire telles que les contraintes sur les pièces adjacentes sont respectées. Il n'est cependant pas obligatoire que toutes les pièces soient placées. Si des pièces sont incorrectement placeés, la fonction renvoie une erreur. 3 Création des puzzles et renvois des solutions Nous dénissons dans cette partie des chiers de données permettant de représenter sous forme textuelle des puzzles et leurs solutions. Ainsi, on représente un puzzle par un chier contenant : la longueur L et la largeur l du puzzle sur la première ligne ; quatre couleurs (sous forme de caractère de l'ensemble {'B','J','R','V'}) représentant une pièce sur les Lxl lignes suivantes. On suppose que la première couleur est en bas de la pièce, la deuxième à gauche, la troisième en haut et la quatrième à droite. Nous appelerons par la suite p1 ,. . . ,pn les pièces du puzzle. Les indices représentent l'ordre des pièces déni par le chier d'entrée. La première à être lue est la pièce numéro 1, la deuxième est la pièce numéro 2, etc. La gure 3 donne un exemple de chier de dimension 4 sur 4, et les pièces de puzzle correspondantes. Question 5 Écrire une fonction make_puzzle qui crée un puzzle à partir d'un chier qui suit le format précédemment décrit. Un chier de puzzle peut facilement être étendu en un chier contenant en plus une solution. Il sut pour ce faire de rajouter à la n de chaque ligne qui décrit une pièce trois entiers : la ligne du puzzle où est placée la pièce (on considérera que la première ligne est la ligne 1 et que les pièces non placées sont sur la ligne 0), la colonne où est placée la pièce (on adoptera les mêmes conventions que pour les lignes), et la rotation eectuée dans le sens des aiguilles d'une montre (soit 0, soit 90, soit 180, soit 270). 2 Question 6 Écrire une fonction write_solution qui génère le chier solution d'un puzzle. 4 Algorithmes de résolution proposés Nous allons maintenant tenter de résoudre simplement ce type de problèmes. Le premier algorithme envisageable consiste à construire le puzzle ligne par ligne, en commançant par la gauche et le haut du puzzle. Une pièce pi ne peut être placée que si elle respecte les contraintes de couleurs et qu'aucune pièce pj pour j < i ne peut être placée à sa place. Les rotations sont évidemment autorisées et toujours réalisées dans le sens des aiguilles d'une montre. Quand aucune pièce ne peut être placée, l'algorithme prend n. Question 7 Implanter l'heuristique dénie ci-dessus. L'heuristique que nous avons décrite a pour principal défaut de laisser toute une partie du puzzle vide, alors que seule une case ne peut vraiment pas être remplie (celle sur laquelle l'algorithme s'est arrêté). Question 8 Reprendre l'heuristique de la question 7 de façon à laisser vide une case lorsqu'aucune pièce ne peut être placée, mais à continuer dès la case suivante selon le même principe. Cette solution n'étant pas encore satisfaisante, puisqu'il reste des cases libres, nous souhaitons l'améliorer encore. Une amélioration est possible si l'on considère que des pièces proches peuvent parfois être échangées sans enlever de pièces. Par exemple, une pièce p posée à coté d'une case vide peut être remplacée par une autre pièce p0 (non encore posée) qui a en commun avec p les cotés qui sont adjacents à des pièces du puzzle. Cet échange peut alors permettre à de nouvelles pièces d'être posées. Question 9 Écrire une fonction qui détermine si une pièce peut prendre la place d'une autre dans le puzzle. L'utiliser ensuite pour améliorer l'algorithme de la question 8. 5 À vous de jouer ! Question 10 Écrire un algorithme de résolution de puzzle et le comparer avec l'algorithme de la question 9. 3