Autour des Sudoku
Go to file
Éric Wegrzynowski bebc04a0ab modif gif animé
2021-01-11 10:14:49 +01:00
bdd restructuration arborescence 2021-01-07 11:13:30 +01:00
images modif gif animé 2021-01-11 10:14:49 +01:00
main1.py restructuration arborescence 2021-01-07 11:13:30 +01:00
main2.py restructuration arborescence 2021-01-07 11:13:30 +01:00
main3.py restructuration arborescence 2021-01-07 11:13:30 +01:00
main4.py restructuration arborescence 2021-01-07 11:13:30 +01:00
main5.py coquille dans README + modf main5 2021-01-08 18:25:15 +01:00
main6.py ajout script main6.py 2021-01-08 11:54:45 +01:00
main7.py modif gif animé 2021-01-11 10:14:49 +01:00
README.md coquille dans README + modf main5 2021-01-08 18:25:15 +01:00
sudoku_grid.py correction bugs + cration GIF animé 2021-01-08 18:23:03 +01:00
sudoku_mondrian.py correction bugs + cration GIF animé 2021-01-08 18:23:03 +01:00
sudoku_solver.py correction bugs + cration GIF animé 2021-01-08 18:23:03 +01:00

Autour des Sudoku

Diverses variations autour des Sudoku.

Licence

Tous les documents se trouvent ici avec la licence Creative Commons CC BY-NC-SA.

Description des fichiers

  • sudoku_grid.py : module définissant une classe SudokuGrid pour représenter les grilles de Sudoku.
  • sudoku_solver.py : module définissant une fonction solve pour la résolution des grilles de Sudoku.
  • sudoku_mondrian.py : module permettant de produire des images représentant des grilles de Sudoku colorées « à la Mondrian ».
  • main1.py : script de résolution d'une grille décrite en argument sur la ligne de commande.
  • main2.py : script de résolution d'une grille contenue dans un fichier. Les solutions sont affichées dans le terminal.
  • main3.py : script de résolution de toutes les grilles contenues dans un fichier. Les solutions sont inscrites dans un fichier.
  • main4.py : script de résolution d'une grille décrite sur la ligne de commande, et qui produit une image représentant la recherche des solutions.
  • main5.py : scripy de résolution d'une grille décrite sur la ligne de commande, qui visualise le remplissage progressif de la grille.
  • main6.py : script produisant une représentation « à la Mondrian » d'une grille décrite sur la ligne de commande.
  • bdd/sudokus.bdd : un fichier texte contenant la description de 5000 grilles de Sudoku ayant toutes une seule solution.
  • bdd/sudoku17.bdd : un fichier texte contenant la description de 49151 grilles de Sudoku n'ayant que 17 cases remplis et ayant toutes une seule solution.

Solveurs de Sudoku

Exemples d'utilisation

Tous les exemples qui suivent s'exécutent dans un terminal de commandes (shell). Ils ont tous été testés sur une machine Linux (Debian). Dans les exemples qui suivent, le symbole $ désigne le prompt du terminal. Et les fichiers main?.py sont supposés avoir le droit d'exécution (si ce n'est pas le cas, il faut remplacer ./main?.py par python3 main?.py.

Résoudre une grille de Sudoku décrite sur la ligne de commande

Avec le script main1.py on peut résoudre toute grille de Sudoku décrite sur la ligne de commande.

Une grille de Sudoku est décrite sur la ligne de commande par une succession de 81 caractères compris entre 0 et 9 (0 pour une case vide). Les neuf premiers caractères représentent la première ligne de la grille, les neuf suivants la deuxième ligne, etc ...

À titre d'exemples, avec la grille

 +-------+-------+-------+
 | 9 . 6 | . 2 8 | . . 3 |
 | . 4 . | 5 . . | . . 1 |
 | . 8 . | 9 . . | . 4 . |
 +-------+-------+-------+
 | 6 . . | . . . | . 7 . |
 | . . 8 | 2 . 6 | 9 . . |
 | . 3 . | . . . | . . 5 |
 +-------+-------+-------+
 | . 5 . | . . 3 | . 6 . |
 | 1 . . | . . 2 | . 8 . |
 | 2 . . | 8 7 . | 5 . . |
 +-------+-------+-------+

on obtient une seule solution

$ ./main1.py 906028003040500001080900040600000070008206900030000005050003060100002080200870500
Sudoku to solve
+-------+-------+-------+
| 9 . 6 | . 2 8 | . . 3 |
| . 4 . | 5 . . | . . 1 |
| . 8 . | 9 . . | . 4 . |
+-------+-------+-------+
| 6 . . | . . . | . 7 . |
| . . 8 | 2 . 6 | 9 . . |
| . 3 . | . . . | . . 5 |
+-------+-------+-------+
| . 5 . | . . 3 | . 6 . |
| 1 . . | . . 2 | . 8 . |
| 2 . . | 8 7 . | 5 . . |
+-------+-------+-------+
Number of solution(s): 1
--
Solution 1
+-------+-------+-------+
| 9 1 6 | 4 2 8 | 7 5 3 |
| 3 4 2 | 5 6 7 | 8 9 1 |
| 7 8 5 | 9 3 1 | 2 4 6 |
+-------+-------+-------+
| 6 2 9 | 3 4 5 | 1 7 8 |
| 5 7 8 | 2 1 6 | 9 3 4 |
| 4 3 1 | 7 8 9 | 6 2 5 |
+-------+-------+-------+
| 8 5 7 | 1 9 3 | 4 6 2 |
| 1 9 4 | 6 5 2 | 3 8 7 |
| 2 6 3 | 8 7 4 | 5 1 9 |
+-------+-------+-------+
--

Et avec la grille

 +-------+-------+-------+
 | 9 . 6 | . 2 8 | . . 3 |
 | . 4 . | 5 . . | . . 1 |
 | . 8 . | 9 . . | . 4 . |
 +-------+-------+-------+
 | 6 . . | . . . | . 7 . |
 | . . 8 | 2 . 6 | 9 . . |
 | . 3 . | . . . | . . 5 |
 +-------+-------+-------+
 | . 5 . | . . 3 | . 6 . |
 | 1 . . | . . 2 | . 8 . |
 | 2 . . | 8 7 . | . . . |
 +-------+-------+-------+

on obtient deux solutions

$ ./main1.py 906028003040500001080900040600000070008206900030000005050003060100002080200870000
Sudoku to solve
+-------+-------+-------+
| 9 . 6 | . 2 8 | . . 3 |
| . 4 . | 5 . . | . . 1 |
| . 8 . | 9 . . | . 4 . |
+-------+-------+-------+
| 6 . . | . . . | . 7 . |
| . . 8 | 2 . 6 | 9 . . |
| . 3 . | . . . | . . 5 |
+-------+-------+-------+
| . 5 . | . . 3 | . 6 . |
| 1 . . | . . 2 | . 8 . |
| 2 . . | 8 7 . | . . . |
+-------+-------+-------+
Number of solution(s): 2
--
Solution 1
+-------+-------+-------+
| 9 1 6 | 4 2 8 | 7 5 3 |
| 3 4 2 | 5 6 7 | 8 9 1 |
| 7 8 5 | 9 3 1 | 2 4 6 |
+-------+-------+-------+
| 6 2 9 | 3 4 5 | 1 7 8 |
| 5 7 8 | 2 1 6 | 9 3 4 |
| 4 3 1 | 7 8 9 | 6 2 5 |
+-------+-------+-------+
| 8 5 7 | 1 9 3 | 4 6 2 |
| 1 9 4 | 6 5 2 | 3 8 7 |
| 2 6 3 | 8 7 4 | 5 1 9 |
+-------+-------+-------+
--
Solution 2
+-------+-------+-------+
| 9 1 6 | 4 2 8 | 7 5 3 |
| 3 4 2 | 5 6 7 | 8 9 1 |
| 7 8 5 | 9 3 1 | 2 4 6 |
+-------+-------+-------+
| 6 2 9 | 3 5 4 | 1 7 8 |
| 5 7 8 | 2 1 6 | 9 3 4 |
| 4 3 1 | 7 8 9 | 6 2 5 |
+-------+-------+-------+
| 8 5 7 | 1 9 3 | 4 6 2 |
| 1 9 3 | 6 4 2 | 5 8 7 |
| 2 6 4 | 8 7 5 | 3 1 9 |
+-------+-------+-------+
--

Enfin avec la grille

 +-------+-------+-------+
 | 9 7 6 | . 2 8 | . . 3 |
 | . 4 . | 5 . . | . . 1 |
 | . 8 . | 9 . . | . 4 . |
 +-------+-------+-------+
 | 6 . . | . . . | . 7 . |
 | . . 8 | 2 . 6 | 9 . . |
 | . 3 . | . . . | . . 5 |
 +-------+-------+-------+
 | . 5 . | . . 3 | . 6 . |
 | 1 . . | . . 2 | . 8 . |
 | 2 . . | 8 7 . | 5 . . |
 +-------+-------+-------+

on n'obtient aucune solution

$ ./main1.py 976028003040500001080900040600000070008206900030000005050003060100002080200870500
Sudoku to solve
+-------+-------+-------+
| 9 7 6 | . 2 8 | . . 3 |
| . 4 . | 5 . . | . . 1 |
| . 8 . | 9 . . | . 4 . |
+-------+-------+-------+
| 6 . . | . . . | . 7 . |
| . . 8 | 2 . 6 | 9 . . |
| . 3 . | . . . | . . 5 |
+-------+-------+-------+
| . 5 . | . . 3 | . 6 . |
| 1 . . | . . 2 | . 8 . |
| 2 . . | 8 7 . | 5 . . |
+-------+-------+-------+
Number of solution(s): 0
--

Résoudre une grille de Sudoku décrite dans un fichier texte

Les grilles de Sudoku peuvent être décrites dans des fichiers texte. C'est le cas des deux fichiers bdd/sudokus.bdd et bdd/sudoku17.bdd qui contiennent chacun plusieurs milliers de grilles de Sudoku. Ces grilles sont décrites comme précédemment par des chaînes de 81 caractères compris entre 0 et 9. Une description peut être précédée par un : et dans ce cas les caractères qui précèdent sont ignorés.

Voici comment résoudre la première grille du fichier bdd/sudokus.bdd

$ ./main2.py bdd/sudokus.bdd 0
Sudoku to solve
+-------+-------+-------+
| 4 9 . | . . 1 | . . 7 |
| . . . | . 4 5 | . 3 . |
| 3 8 2 | 6 . . | . 5 . |
+-------+-------+-------+
| . . 3 | . 7 . | 4 . 1 |
| 8 . . | 9 . 2 | . . 5 |
| 9 . 7 | . 3 . | 6 . . |
+-------+-------+-------+
| . 3 . | . . 6 | 5 2 9 |
| . 2 . | 8 5 . | . . . |
| 5 . . | 7 . . | . 1 3 |
+-------+-------+-------+
Number of solution(s): 1
--
Solution 1
+-------+-------+-------+
| 4 9 5 | 3 8 1 | 2 6 7 |
| 6 7 1 | 2 4 5 | 9 3 8 |
| 3 8 2 | 6 9 7 | 1 5 4 |
+-------+-------+-------+
| 2 6 3 | 5 7 8 | 4 9 1 |
| 8 1 4 | 9 6 2 | 3 7 5 |
| 9 5 7 | 1 3 4 | 6 8 2 |
+-------+-------+-------+
| 7 3 8 | 4 1 6 | 5 2 9 |
| 1 2 9 | 8 5 3 | 7 4 6 |
| 5 4 6 | 7 2 9 | 8 1 3 |
+-------+-------+-------+
--

Résoudre toutes les grilles décrites dans un fichier

Le script main3.py permet de résoudre toutes les grilles décrites dans un fichier dont on donne le nom dans la ligne de commandes.

$ ./main3.py bdd/sudokus.bdd

L'exécution de cette commande n'affiche rien. Elle se contente de produire un fichier dont le nom est celui passé en argument suivi de l'extension .sol. Chaque ligne de ce fichier contient

  1. les 81 caractères de la grille d'origine (avec éventuellement quelques mentions qui la précèdent) suivis d'un : ;
  2. le caractère y si la solution est unique ou le caractère n s'il n'y a aucune ou plus d'une solution ;
  3. les solutions séparées par des :.

Voici les trois premières lignes du fichier bdd/sudokus.bdd.sol produit par la commande précédente :

easy:490001007000045030382600050003070401800902005907030600030006529020850000500700013:y:495381267671245938382697154263578491814962375957134682738416529129853746546729813
fiendish:020500730000490050500000000019207005060000070400908120000000006080029000096005040:y:921586734637491258548372691819237465263154879475968123152743986384629517796815342
hard:050008460004000038000030107000920003020000050700086000208090000460000900015700080:y:352178469174269538896435127581924673629317854743586291238691745467853912915742386

Toutes les grilles sont résolues

Visualiser la recherche de solution avec le script main4.py

Pour utiliser ce script il est supposé que la suite logicielle graphviz est installée.

Le script main4.py permet de produire une image représentant l'arbre de recherche des solutions parcouru par l'algorithme de résolution mis en œuvre dans le module sudoku_solver.

Son utilisation nécessite deux arguments sur la ligne de commande :

  1. une chaîne de 81 caractères représentant la grille à résoudre
  2. un nom pour les deux fichiers qui seront produits. Ce nom sera automatiquement complété de l'extension .dot pour l'un de ces deux fichiers qui contiendra une description de l'arbre dans le langage de description de graphes de graphviz. L'autre fichier qui aura un nom complété de l'extension .png contiendra une image au format PNG de cet arbre.

Voici ce qu'on obtient en reprenant les trois exemples précédents.

Exemple 1

$ ./main4.py 906028003040500001080900040600000070008206900030000005050003060100002080200870500 images/arbre_exple1
Sudoku to solve
+-------+-------+-------+
| 9 . 6 | . 2 8 | . . 3 |
| . 4 . | 5 . . | . . 1 |
| . 8 . | 9 . . | . 4 . |
+-------+-------+-------+
| 6 . . | . . . | . 7 . |
| . . 8 | 2 . 6 | 9 . . |
| . 3 . | . . . | . . 5 |
+-------+-------+-------+
| . 5 . | . . 3 | . 6 . |
| 1 . . | . . 2 | . 8 . |
| 2 . . | 8 7 . | 5 . . |
+-------+-------+-------+
Number of solution(s): 1
--
Solution 1
+-------+-------+-------+
| 9 1 6 | 4 2 8 | 7 5 3 |
| 3 4 2 | 5 6 7 | 8 9 1 |
| 7 8 5 | 9 3 1 | 2 4 6 |
+-------+-------+-------+
| 6 2 9 | 3 4 5 | 1 7 8 |
| 5 7 8 | 2 1 6 | 9 3 4 |
| 4 3 1 | 7 8 9 | 6 2 5 |
+-------+-------+-------+
| 8 5 7 | 1 9 3 | 4 6 2 |
| 1 9 4 | 6 5 2 | 3 8 7 |
| 2 6 3 | 8 7 4 | 5 1 9 |
+-------+-------+-------+
--

Et voici l'image produite qui montre un arbre filiforme (signe que le sudoku est facile). La grille initiale est marquée en rouge en haut, et l'unique solution est marquée en vert en bas. Le premier nœud accessible depuis le nœud rouge de départ porte la mention ('7', 6, 0). Cela signifie que lors de la résolution, la première case remplie a été celle de coordonnée (6, 0) (septième colonne, première ligne) et qu'on y a placé le chiffre 7.

arbre de résolution de l'exemple 1

Exemple 2

$ ./main4.py 906028003040500001080900040600000070008206900030000005050003060100002080200870000 images/arbre_exple2
Sudoku to solve
+-------+-------+-------+
| 9 . 6 | . 2 8 | . . 3 |
| . 4 . | 5 . . | . . 1 |
| . 8 . | 9 . . | . 4 . |
+-------+-------+-------+
| 6 . . | . . . | . 7 . |
| . . 8 | 2 . 6 | 9 . . |
| . 3 . | . . . | . . 5 |
+-------+-------+-------+
| . 5 . | . . 3 | . 6 . |
| 1 . . | . . 2 | . 8 . |
| 2 . . | 8 7 . | . . . |
+-------+-------+-------+
Number of solution(s): 2
--
Solution 1
+-------+-------+-------+
| 9 1 6 | 4 2 8 | 7 5 3 |
| 3 4 2 | 5 6 7 | 8 9 1 |
| 7 8 5 | 9 3 1 | 2 4 6 |
+-------+-------+-------+
| 6 2 9 | 3 4 5 | 1 7 8 |
| 5 7 8 | 2 1 6 | 9 3 4 |
| 4 3 1 | 7 8 9 | 6 2 5 |
+-------+-------+-------+
| 8 5 7 | 1 9 3 | 4 6 2 |
| 1 9 4 | 6 5 2 | 3 8 7 |
| 2 6 3 | 8 7 4 | 5 1 9 |
+-------+-------+-------+
--
Solution 2
+-------+-------+-------+
| 9 1 6 | 4 2 8 | 7 5 3 |
| 3 4 2 | 5 6 7 | 8 9 1 |
| 7 8 5 | 9 3 1 | 2 4 6 |
+-------+-------+-------+
| 6 2 9 | 3 5 4 | 1 7 8 |
| 5 7 8 | 2 1 6 | 9 3 4 |
| 4 3 1 | 7 8 9 | 6 2 5 |
+-------+-------+-------+
| 8 5 7 | 1 9 3 | 4 6 2 |
| 1 9 3 | 6 4 2 | 5 8 7 |
| 2 6 4 | 8 7 5 | 3 1 9 |
+-------+-------+-------+

L'image produite montre que pendant un certain nombre d'étapes le parcours a été linéaire (aucun choix), puis une alternative s'est révélée chaque branche de cette alternative aboutissant à une solution, d'où les deux nœuds verts.

arbre de résolution de l'exemple 2

Exemple 3

$ ./main4.py 976028003040500001080900040600000070008206900030000005050003060100002080200870500 images/arbre_exple3
Sudoku to solve
+-------+-------+-------+
| 9 7 6 | . 2 8 | . . 3 |
| . 4 . | 5 . . | . . 1 |
| . 8 . | 9 . . | . 4 . |
+-------+-------+-------+
| 6 . . | . . . | . 7 . |
| . . 8 | 2 . 6 | 9 . . |
| . 3 . | . . . | . . 5 |
+-------+-------+-------+
| . 5 . | . . 3 | . 6 . |
| 1 . . | . . 2 | . 8 . |
| 2 . . | 8 7 . | 5 . . |
+-------+-------+-------+
Number of solution(s): 0
--

L'image produite montre un arbre ne comprenant qu'un seul nœud dont aucun vert. Cela provient du fait qu'une case impossible à remplir en respectant les contraintes a été découverte : la case (0, 6).

arbre de résolution de l'exemple 3

Avec la grille ci-dessous (grille de la ligne 43 du fichier bdd/sudokus.bdd)

+-------+-------+-------+
| 2 . . | . 5 . | 8 4 . |
| . 1 . | 7 9 . | 5 . . |
| . . . | . . 4 | . . . |
+-------+-------+-------+
| . 8 1 | . . . | 2 . 9 |
| 3 . . | . . . | . . 5 |
| 7 . 6 | . . . | 3 1 . |
+-------+-------+-------+
| . . . | 9 . . | . . . |
| . . 8 | . 2 3 | . 5 . |
| . 6 3 | . 1 . | . . 7 |
+-------+-------+-------+

l'arbre de résolution révèle que cette grille n'a qu'une seule solution (un seul nœud vert), mais les nombreux branchements révèlent aussi de nombreuses impasses (fausse route) empruntées durant la recherche.

Arbre de résolution d'un sudoku difficile

Visualiser la recherche de solution avec main5.py

Ce scrit exploite les codes ANSI.

Le script main5.py prend deux paramètres sur la ligne de commandes

  1. la description de la grille de Sudoku à résoudre sous forme d'une chaîne de 81 caractères ;
  2. un nombre exprimant la durée de pause (en secondes) entre deux coups successifs.

Il produit en sortie un affichage de la grille sur la sortie standard que l'on peut voir se remplir petit à petit (après avoir tapé la touche Entrée).

Grille de Sudoku colorée « à la Mondrian » avec main6.py

Le script main6.py prend un ou deux paramètres sur la ligne de commandes

  1. la description de la grille de Sudoku à résoudre sous forme d'une chaîne de 81 caractères ;
  2. et optionnellement un nom de fichier dans lequel l'image produite sera sauvegardée. L'extension donnée au nom de fichier détermine le format se sauvegarde. Ces extensions peuvent être .png, .jpg, .gif et d'autres encore supportées par le module PIL.

Par exemple, la commande

 $ ./main6.py 906028003040500001080900040600000070008206900030000005050003060100002080200870500 images/mondrian_exple1.png

produit l'ouverture d'une fenêtre montrant l'image

coloriage de la grille de l'exemple 1

et un fichier nommé mondrian_exple1.png dans le dossier images.

Création d'un GIF animé

$ ./main7.py 906028003040500001080900040600000070008206900030000005050003060100002080200870500 images/mondrian_exple1_resolution

resolution animée de la grille de l'exemple 1