TD d`Éléments d`Algorithmique n 7 Correction sudoku

publicité
Université Paris Diderot - L2 informatique
Année 2015–2016
TD d’Éléments d’Algorithmique n◦ 7
Correction sudoku
Une grille de sudoku est un tableau à deux dimensions de taille 9 × 9 – on parle aussi de
matrice carrée 9 × 9 –, composé de 9 sous-grilles carrées 3 × 3. Une instance de sudoku est un
remplissage partiel de la grille par des entiers entre 1 et 9.
Une solution d’une instance de sudoku est une grille complétement remplie par des entiers
entre 1 et 9, telle que :
• chaque ligne, colonne et sous grille de la solution est sans répétition, et contient donc une
et une seule fois chaque entier de 1 à 9.
• les cases initialement remplies de l’instance ne changent pas de valeur dans la solution.
On peut voir une instance de sudoku comme une étape dans la résolution d’une grille. Voici
une instance de sudoku et une de ses solutions.
3
1
8
5
7
3
2
4
7
1
6
8
5
9
3
2
5
4
7
1
9
5
4
1
3
6
8
2
5
9
1
7
4
5
9
1
3
4
7
6
2
8
4
1
9
5
8
6
2
3
7
6
7
2
9
3
4
8
1
5
8
3
5
7
2
1
4
6
9
7
2
3
4
1
5
9
8
6
1
8
4
6
9
3
7
5
2
9
5
6
8
7
2
3
4
1
Il existe environ 6, 67 × 1021 solutions distinctes de l’instance vide (la grille sans cases remplies).
Plusieurs algorithmes peuvent être tentés, voici ceux proposés par vos camades :
• Algorithme naïf : générer toutes les grilles possibles de sudoku. Pour chacune d’entre elle,
vérifier qu’elle est valide puis qu’elle est compatible avec la grille pré-remplie.
• S’occuper d’abord des sous-grilles. Pour chacune des 9 sous grilles, générer toutes les
sous-grilles 3 × 3 (remplies avec des nombre de 1 à 9) possibles et garder que celle qui
sont compatibles avec la grille pré-remplie. Puis dans un second temps, essayer toutes les
façons d’imbriquer ces 9 sous grilles et garder que celle qui sont valides.
• Algorithme «naturel» : parcourir les cases une par une et vérifier pour chacune d’entre
elle si on a le choix du nombre à mettre (si par exemple la colonne de la grille est déjà
remplie avec 1,4,5, la ligne avec 2,6,9 et le sous carré avec 7,8,9, alors on sait que la case
doit être remplie avec un 3). Si c’est le cas la remplir et continuer jusqu’à ce que le sudoku
soit rempli.
Une telle case n’existant généralement pas, on pourra se contenter de case ayant peu de
choix (2 ou 3 possibilités).
Voici la correction de l’algorithme naïf. Une grille est un tableau de tableaux (ou une matrice)
de taille 9 × 9.
1
1. Algorithme Verif : il attend une grille de sudoku remplie et vérifie si elle est valide,
c’est à dire si chaque ligne, colonne ou sous grille de la solution est sans répétition, et
contient donc une et une seule fois chaque entier de 1 à 9.
Verif(Grille G)
booléen b = true
Pour i allant de 0 à 8 faire :
Pour j allant de 0 à 8 faire :
pour k allant de 0 à 8 faire :
Si k != j ET G[i][j] == G[i][k] Alors
b = false
Fin Si
Si k!=j ET G[j][i] == G[k][i] alors
b = false
Fin Si
Fin pour
Fin pour
Fin pour
Pour i,j allant de 0 à 2 faire :
pour k1,l1 allant de 0 à 2 faire :
pour k2,l2 allant de 0 à 2 faire :
Si (k1,l1) != (k2,l2) ET G[i+k1][j+l1] == G[i+k2][j+l2] alors
b = false
Fin Si
Fin pour
Fin pour
Fin pour
Retourner (b)
2. Algorithme Compa : il attend une grille G de sudoku complètement remplie et une
grille M de sudoku pré-remplie (certaines cases auront des valeurs nulle). Il vérifie que
la grille remplie prolonge bien la grille pré-remplie.
Compa(Grille G, Grille M)
booléen b = true
Pour i allant de 0 à 8 faire :
Pour j allant de 0 à 8 faire :
Si M[i][j] != NULL ET M[i][j] != G[i][j] alors
b = false
Fin Si
Fin Pour
Fin pour
Rendre (b)
3. Algorithme ArbreSoluce. Il va générer un arbre dont chaque sommet à 9 fils. Chaque
sommet représente une façon de remplir partiellement la grille, ses 9 fils étant les 9 façons
différentes de remplir une case de plus. @ est la concaténation de deux entiers : 23 @ 6
= 236.
Pour cela on va utiliser un algorithme ArbreSoluceAux(int n, arbre A) attendant un
arbre et un entier n.
2
ArbreSoluceAux(int n, arbre A)
Si n == 0 alors
rendre A
Sinon
Pour i allant de 1 à 9 faire :
c = ALLOC()
c->Val = A->Val @ i
A ->Fils(i) = c
ArbreSoluceAux(n-1,c)
Fin pour
Fin si
ArbreSoluce()
A = Alloc()
ArbreSoluceAux(A,9)
retourne(A)
4. Algorithme naïf : Il attend une grille pré-remplie M . Il commence par générer toutes les
grilles avec ArbreSoluce, puis les parcours une par une (une grille remplie est une feuille
de l’arbre généré par ArbreSoluce), Vérifie qu’elle est compatible avec M et qu’elle est
valide.
Naif(Grille M)
A = ArbreSoluce()
Pile P
booléen b
P.push(A)
Tant que P non vide faire :
s = P.pull()
b = true
Pour i allant de 0 à 8 faire :
Si s->Fils(i) NON NULL alors
P.Push(s->Fils(i))
b = false
Fin faire
Si b == true alors :
G = s->Val
Si Compa(G,M) == true ET Verif(G) == true alors :
Retourne (G)
Fin si
Fin si
Fin tant
Remarquez que nous faisons un parcours préfixe de l’arbre. Le booléen b est juste là pour
marquer les feuilles : il vaut false si s a un fils, true si il en a aucun.
3
Téléchargement