Projet d Informatique Résolution et génération de Sudoku Contact : pierre.yger@unic.cnrs-gif.fr 10 septembre 2009 1 Principe du Sudoku Le sudoku, défini en 1979 par l Américain Howard Garns, est un jeu désormais courant basé sur le principe dit du carré latin. Son principe est relativement simple : le but du jeu est de remplir une grille avec une série de chiffres (ou de lettres ou de symboles) tous différents, qui ne se trouvent jamais plus d une fois sur une même ligne, dans une même colonne ou dans une même sous-grille. La plupart du temps, les symboles sont des chiffres allant de 1 à 9, les sous-grilles étant alors des carrés de taille 3x3. Quelques symboles sont déjà disposés dans la grille, ce qui autorise une résolution progressive du problème complet (voir Figure 1). Fig. 1 Exemple de grille de Sudoku classique, avec sous blocs de taille 3x3. A essayer de résoudre, à la main d abord... 1.1 Résolution automatique 1.1.1 Programmation par contraintes Le sudoku fait partie des problèmes algorithmiques qui se résolvent par programmation dite par contraintes (PPC), et même si nous ne les utiliserons pas ici, sachez qu il existe des langages de programmation spécialement 1
orienté vers ce type de problème (Prolog). On cherche en effet dans un ensemble fini de valeurs (ici l ensemble des nombres de la grille manquants) ceux statisfaisant un ensemble de contraintes (ici données par les informations extraites des symboles déjà présent dans la grille). Le but de la PPC est donc de rechercher un ensemble de valeurs, étant donné des contraintes, et d essayer d éviter de tester tous les élements. On doit utiliser les contraintes pour restreindre l espace des solutions à chercher, et donc filtrer les solutions impossibles. Si on essayait par brute force toutes les combinaisons, avec plus de 50 cases vides dans une grille de sudoku 9x9, il faudrait tester plus de 9 50 = 5 10 47 grilles possibles. Impossible. 1.1.2 Algorithme du backtracking Le backtracking est une méthode pour contruire de manière incrémentale une solution à un problème, en abandonnant des solutions dès que l algorithme s aperçoit que ces dernières ne vont pas respecter toutes les contraintes du problème. C est un algorihtme récursif dont le principe peut être illustré via un arbre. Apliquée au Sudoku, l idée est la suivante : on cherche à chaque étape la case avec le plus de contraintes (le moins de possibilités), on la remplit, et on itère le processus. Par récursivité, on contruit un arbre des possibles (voir Figure 2) : La racine (le sommet de l arbre) correspond à la première case choisie. Les noeuds correspondent aux différentes façons de remplir les cases. Chaque arc correspond à un coup joué. Aux feuilles, tout en bas de l arbre, se trouvent la ou les fins de parties. (En general, les grilles de Sudoku ont une unique solution) Un chemin complet, allant de la racine à une feuille, décrit une partie possible Chaque fois que l on arrive sur une solution impossible, on revient en arrière dans l arbre des solutions. L atout du backtracking est que la recursivité permet de ne pas contruire entièrement l arbre de toutes les solutions. On part explorer des branches, et tant que ces dernières n aboutissent pas à des contradictions ou des impossibilités on continue à descendre en profondeur. Au moindre problème, on revient en arrière et on explore une autre direction. 1.2 Travail demandé Vous fournirez un code ***commenté*** (en C ou autre) permettant, avec une interface graphique basique en mode console, de fournir la solution d une grille de Sudoku. Les contraintes à respecter (non obligatoires, mais à avoir en tête) sont les suivantes : 2
Fig. 2 Arbre construit par backtracking. En rouge, la trajectoire conduisant à la solution, depuis la case i jusqu aux feuilles terminales de l arbre. 6 8-3 5 - - - - - - - - 1 - - 2 - - - 7-6 - 9 - - 1 - - - - - - - - 3-5 - 9-1 - 2 - - - - - - - - 9 - - 3-2 - 8 - - - 6 - - 7 - - - - - - - - 4 5-3 1 Tab. 1 Représentation d une grille en format texte. Un espace sépare les charactères, et les cases vides sont symbolisées par le symbole -. La grille devra être lue depuis un fichier, stockée sous forme de texte simple (voir Table 1) Un mode devra laisser le soin de résoudre la grille soit à la main, soit à l aide du backtracking La résolution de la grille devra indiquer le temps précis mis par l algorithme pour la résolution. Le code sera le plus général possible, et devra être facilement capable de résoudre un sudoku de taille quelconque (grille de taille 5x5 par exemple, avec des chiffres allant de 0 à 25). 1.3 Quelques pistes pour le code Les indications données ici ne sont là qu à titre informatif et il n est donc pas obligatoire de les suivre au pieds de la lettre. Réfléchissez juste bien à votre code avant de vous lancer, et aux différentes fonctions qui vont être nécessaires. Vous pouvez commencer par coder d abord le jeu dans sa version où un humain resout la grille, utilisant a priori des fonctions telles que : 3
config partie() affiche un menu permettant de selectionner le type de resolution (humain ou backtracking) affiche grille() affiche le jeu sur la console coups grille() retourne, pour une configuration ou case donnée, tous les coups jouables possibles. Si un joueur veut jouer un coup qui n est pas dans cette liste, le coup doit être interdit. Pour ce qui est de la partie backtracking, vous aurez besoin de fonctions telles que : charge grille() charge la grille depuis un fichier. backtrack() calcule le coup a jouer dans la meilleure case disponible. backtrack n() résout la grille de taille nxn 2 Genération des grilles Cette partie est volontairement laissé quasi vide, pour vous laisser chercher comment générer des grilles valides de Sudoku. Ce problème s inscrit dans celui, plus général en informatique, du coloriage de graphe. Vous effectuerez une recherche personnelle sur le sujet. Trouvez des exemples de problèmes se ramenant au coloriage de graphes. Ce problème, dans sa forme générale, est dit NP complet. Qu est-ce qu un problème NP complet? Trouvez d autres exemples de tels problèmes, cruciaux en informatique. Vous avez toute latitude pour trouver comment générer des grilles, voire les sauver. J attends dans vos rapports une description commentée de la méthode que vous avez déployée. Notez qu une grille de Sudoku à une solution unique. 3 Pour aller plus loin... Faire une interface graphique du jeu, quand tout fonctionne d abord en mode console. Tester son algorithme sur des grilles de taille nxn (création et résolution) 3.1 Compte-rendu Ce travail n est important que dans la façon dont vous l aborderez. Il est important que vous fassiez quelques recherches par vous même sur l algorithme, que vous en compreniez son fonctionnement et ses limites. Un compte rendu intermédiaire sera attendu à mi parcours donc pensez à essayer de rédiger votre rapport en même temps que votre code. Dans le rapport, on trouvera une explication des fonctions importantes, une justification des 4
structures de données mises en place pour représenter l état du jeu, etc... Pas la peine de recopier le code, vous joindrez les fichiers en annexe. Pour l évaluation, seront prises en compte la clareté du rapport et du code. Un tournoi entre vos programmes pourra être envisagé si tout le monde à finit à temps, sur des grilles imposées (de difficulté croissante) en regardant lequel trouve les solutions le plus rapidement possible (avec le timing que vous devrez avoir implémenté). Rappel pour le code : L explication, avec des mots, et les commentaires du code sont aussi important que le code lui même. 5