Exercices - Grille de Sudoku☘
Si vous ne connaissez pas encore les règles du Sudoku, cherchez sur la toile !
On dispose de trois grilles de Sudoku :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
Votre mission est de vérifier que ces grilles ont été correctement complétées, c'est-à-dire qu'elles ne contiennent pas d'erreur :
- pas de répétition d'un même chiffre dans une ligne,
- pas de répétition d'un même chiffre dans une colonne,
- pas de répétition d'un même chiffre dans l'un des 9 carrés 3×3.
Téléchargez le fichier « à trous » ProgB05.70.py
(clic droit -> [Enregistrer sous]) et enregistrez-le dans le dossier
[B05_Tableaux_de_Tableaux]
.
Ajoutez ensuite des tests personnalisés dans la partie principale du programme. Vous pourrez facilement produire une grille fausse pour vos tests !
Rappels
- Enregistrez le fichier à compléter dans le dossier
[B05-Tableaux_de_Tableaux]
avec le nom donné à l'exercice :ProgB05.70.py
. - Pour exécuter ce programme, il suffit de le sauvegarder puis d'appuyer sur la touche
[F5]
. - Le programme principal doit contenir un appel au module
doctest
:##----- Programme principal et tests -----## if __name__ == '__main__': import doctest doctest.testmod()
Partie 1 - Ligne correcte☘
Complétez les définitions des fonctions suivantes :
-
verif_ligne()
qui renvoieTrue
si une ligne contient une fois et une seule chacun des chiffres de 1 à 9.1 2 3 4 5 6 7
def verif_ligne(grille, numero_de_ligne): """ grille - matrice sudoku numero_de_ligne - numéro de ligne de la grille (entre 0 et 8) Sortie: bool - True si la ligne contient chacun des chiffres une fois et une seule, False sinon. """
Une piste
On peut définir comme variable globale (c'est-à-dire en dehors du corps des fonctions) le t-uplet
CHIFFRES = (1,2,3,4,5,6,7,8,9)
pour y faire référence quelle que soit la fonction programmée dans cette page.Solution du 1.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
##----- Constantes -----## CHIFFRES = (1, 2, 3, 4, 5, 6, 7, 8, 9) ##----- Définitions des fonctions -----## def verif_ligne(grille, numero_de_ligne): """ grille - matrice sudoku numero_de_ligne - numéro de ligne de la grille (entre 0 et 8) Sortie: bool - True si la ligne contient chacun des chiffres une fois et une seule, False sinon. """ for chiffre in CHIFFRES: if chiffre not in grille[numero_de_ligne]: return False return True
Attention à la boucle
for
et au test des lignes 13 et 14. En effet, le code :
ne peut pas convenir puisque la ligne13 14
for chiffre in grille[numero_de_ligne]: if chiffre not in CHIFFRES:
[1, 1, 1, 1, 1, 1, 1, 1, 1]
serait considérée comme correcte. En effet, chaque entier de cette ligne est bien dansCHIFFRES
mais ces entiers ne sont pas tous distincts et compris entre1
et9
. -
verif_toutes_lignes()
qui renvoieTrue
si chaque ligne contient une fois et une seule chacun des chiffres de 1 à 9.1 2 3 4 5 6
def verif_toutes_lignes(grille): """ grille - matrice sudoku Sortie: bool - True si chaque ligne respecte les règles du Sudoku, False sinon. """
Solution du 2.
18 19 20 21 22 23 24 25 26 27
def verif_toutes_lignes(grille): """ grille - matrice sudoku Sortie: bool - True si chaque ligne respecte les règles du Sudoku, False sinon. """ for numero_de_ligne in range(9): if not verif_ligne(grille, numero_de_ligne): return False return True
Partie 2 - Colonne correcte☘
Complétez les définitions des fonctions suivantes :
-
verif_colonne()
qui renvoieTrue
si une colonne contient une fois et une seule chacun des chiffres de 1 à 9.1 2 3 4 5 6 7
def verif_colonne(grille, numero_de_colonne): """ grille - matrice sudoku numero_de_colonne - numéro de colonne de la grille (entre 0 et 8) Sortie: bool - True si la colonne contient chacun des chiffres une fois et une seule, False sinon. """
Solution du 1.
Pour faciliter la manipulation, on extrait les valeurs présentent dans la colonne
numero_de_colonne
et on les place dans un tableau nommécolonne
:30 31 32 33 34 35 36 37 38 39 40 41
def verif_colonne(grille, numero_de_colonne): """ grille - matrice sudoku numero_de_colonne - numéro de colonne de la grille (entre 0 et 8) Sortie: bool - True si la colonne contient chacun des chiffres une fois et une seule, False sinon. """ colonne = [grille[num_ligne][numero_de_colonne] for num_ligne in range(9)] for chiffre in CHIFFRES: if chiffre not in colonne: return False return True
-
verif_toutes_colonnes()
qui renvoieTrue
si chaque colonne contient une fois et une seule chacun des chiffres de 1 à 9.1 2 3 4 5 6
def verif_toutes_colonnes(grille): """ grille - matrice sudoku Sortie: bool - True si chaque colonne respecte les règles du Sudoku, False sinon. """
Solution du 2.
44 45 46 47 48 49 50 51 52 53
def verif_toutes_colonnes(grille): """ grille - matrice sudoku Sortie: bool - True si chaque colonne respecte les règles du Sudoku, False sinon. """ for numero_de_colonne in range(9): if not verif_colonne(grille, numero_de_colonne): return False return True
Partie 3 - Repérer les zones carrées☘
Pour traiter le cas des zones carrées, nous allons faire un choix de numérotation des carrés et remarquer que nous pouvons décrire assez facilement les coordonnées de la cellule haut gauche de chaque carré à partir de cette numérotation.
Le choix de la numérotation des carrés est la suivante :
-
Vérifier que la cellule haut-gauche de chaque carré a pour coordonnées le couple
(ligne, colonne)
tel que :ligne = 3 * (numero//3)
colonne = 3 * (numero%3)
où
numero
est le numéro du carré.Solution du 1.
- La cellule haut gauche du carré numéro
0
a pour coordonnées(ligne, colonne)
=(0, 0)
.
Et(3 * (0//3), 3 * (0%3))
=(0, 0)
. - La cellule haut gauche du carré numéro
1
a pour coordonnées(ligne, colonne)
=(0, 3)
.
Et(3 * (1//3), 3 * (1%3))
=(0, 3)
. - La cellule haut gauche du carré numéro
2
a pour coordonnées(ligne, colonne)
=(0, 6)
.
Et(3 * (2//3), 3 * (2%3))
=(0, 6)
. - La cellule haut gauche du carré numéro
3
a pour coordonnées(ligne, colonne)
=(3, 0)
.
Et(3 * (3//3), 3 * (0%3))
=(3, 0)
. - La cellule haut gauche du carré numéro
4
a pour coordonnées(ligne, colonne)
=(3, 3)
.
Et(3 * (4//3), 3 * (4%3))
=(3, 3)
. - etc...
-
En déduire la définition de la fonction suivante permettant de créer le tableau des chiffres contenus par un carré (identifié par son numéro) :
1 2 3 4 5 6
def contenu_carre(grille, numero): """ grille - matrice sudoku numéro - numéro d'une zone carrée Sortie: list - le tableau des chiffres contenus dans le carré """
Solution du 2.
56 57 58 59 60 61 62 63 64 65 66 67 68
def contenu_carre(grille, numero): """ grille - matrice sudoku numéro - numéro d'une zone carrée Sortie: list - le tableau des chiffres contenus dans le carré """ ligneHG = 3*(numero//3) # numéro de ligne de la cellule haute gauche du carré colonneHG = 3*(numero%3) # numéro de colonne de la cellule haute gauche du carré chiffres_du_carre = [] for i in range(ligneHG, ligneHG+3): for j in range(colonneHG, colonneHG+3): chiffres_du_carre.append(grille[i][j]) return chiffres_du_carre
Solution avec une définition par compréhension
56 57 58 59 60 61 62 63 64 65
def contenu_carre(grille, numero): """ grille - matrice sudoku numéro - numéro d'une zone carrée Sortie: list - le tableau des chiffres contenus dans le carré """ ligneHG = 3*(numero//3) # numéro de ligne de la cellule haute gauche du carré colonneHG = 3*(numero%3) # numéro de colonne de la cellule haute gauche du carré return [grille[i][j] for i in range(ligneHG, ligneHG+3) for j in range(colonneHG, colonneHG+3)]
Partie 4 - Zone carrée correcte☘
Complétez les définitions des fonctions suivantes :
-
verif_carre()
qui renvoieTrue
si un des 9 carrés 3×3 contient une fois et une seule chacun des chiffres de 1 à 9.1 2 3 4 5 6 7
def verif_carre(grille, numero): """ grille - matrice sudoku numero - numéro d'une zone carrée (entre 0 et 8) Sortie: bool - True si le carré contient chacun des chiffres une fois et une seule, False sinon. """
Solution du 1.
On fait bien sûr appel à la fonction
contenu_carre()
définie dans la partie précédente.71 72 73 74 75 76 77 78 79 80 81 82
def verif_carre(grille, numero): """ grille - matrice sudoku numero - numéro d'une zone carrée (entre 0 et 8) Sortie: bool - True si le carré contient chacun des chiffres une fois et une seule, False sinon. """ carre = contenu_carre(grille, numero) for chiffre in CHIFFRES: if chiffre not in carre: return False return True
-
verif_tous_carres()
qui renvoieTrue
si chacun des 9 carrés 3×3 contient une fois et une seule chacun des chiffres de 1 à 9.1 2 3 4 5 6
def verif_tous_carres(grille): """ grille - matrice sudoku Sortie: bool - True si chaque carré respecte les règles du Sudoku, False sinon. """
Solution du 2.
85 86 87 88 89 90 91 92 93 94
def verif_tous_carres(grille): """ grille - matrice sudoku Sortie: bool - True si chaque carré respecte les règles du Sudoku, False sinon. """ for numero_de_carre in range(9): if not verif_carre(grille, numero_de_carre): return False return True
Partie 5 - Grille correcte☘
Conclure en complétant la définition de la fonction verif_grille()
qui
vérifie qu'une grille est correctement remplie.
1 2 3 4 5 6 |
|
Une réponse
97 98 99 100 101 102 103 |
|
Le programme complet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
|
Partie 6 - Factorisation de code☘
Dans le code complet de la question précédente, vous pouvez remarquer que les
fonctions verif_toutes_lignes()
, verif_toutes_colonnes()
et
verif_tous_carres()
ont exactement la même structure.
Remplacez ces trois fonctions par une seule fonction verif_blocs()
puis
réécrivez la fonction verif_grille()
à l'aide de cette fonction
verif_blocs()
.
Une solution
##----- Constantes -----##
CHIFFRES = (1,2,3,4,5,6,7,8,9)
##----- Définitions des fonctions -----##
def verif_ligne(grille, numero_de_ligne):
"""
grille - matrice sudoku
numero_de_ligne - numéro de ligne de la grille (entre 0 et 8)
Sortie: bool - True si la ligne contient chacun des chiffres une fois et une seule,
False sinon.
"""
for chiffre in CHIFFRES:
if chiffre not in grille[numero_de_ligne]:
return False
return True
def verif_colonne(grille, numero_de_colonne):
"""
grille - matrice sudoku
numero_de_colonne - numéro de colonne de la grille (entre 0 et 8)
Sortie: bool - True si la colonne contient chacun des chiffres une fois et une seule,
False sinon.
"""
colonne = [grille[num_ligne][numero_de_colonne] for num_ligne in range(9)]
for chiffre in CHIFFRES:
if chiffre not in colonne:
return False
return True
def contenu_carre(grille, numero):
"""
grille - matrice sudoku
numéro - numéro d'une zone carrée
Sortie: list - le tableau des chiffres contenus dans le carré
"""
ligneHG = 3*(numero//3) # numéro de ligne de la cellule haute gauche du carré
colonneHG = 3*(numero%3) # numéro de colonne de la cellule haute gauche du carré
return [grille[i][j] for i in range(ligneHG, ligneHG+3) for j in range(colonneHG, colonneHG+3)]
def verif_carre(grille, numero):
"""
grille - matrice sudoku
numero - numéro d'une zone carrée (entre 0 et 8)
Sortie: bool - True si le carré contient chacun des chiffres une fois et une seule,
False sinon.
"""
carre = contenu_carre(grille, numero)
for chiffre in CHIFFRES:
if chiffre not in carre:
return False
return True
def verif_blocs(grille, fonction_bloc):
"""
grille - matrice sudoku
fonction_bloc - fonction de vérification d'un bloc (ligne, colonne ou carré)
Sortie: bool - True si chaque bloc respecte les règles du Sudoku,
False sinon.
"""
for numero_bloc in range(9):
if not fonction_bloc(grille, numero_bloc):
return False
return True
def verif_grille(grille):
"""
grille - matrice sudoku
Sortie: bool - True si la grille respecte les règles du Sudoku,
False sinon.
"""
if not verif_blocs(grille, verif_ligne):
return False
if not verif_blocs(grille, verif_colonne):
return False
if not verif_blocs(grille, verif_carre):
return False
return True
##----- Tests des fonctions -----##
if __name__ == "__main__":
A = [ [3,6,7,9,4,1,2,8,5],
[1,5,2,6,8,3,4,9,7],
[4,9,8,7,5,2,1,6,3],
[7,4,6,1,9,5,8,3,2],
[8,1,9,2,3,7,6,5,4],
[2,3,5,8,6,4,7,1,9],
[9,2,1,5,7,8,3,4,6],
[5,8,4,3,2,6,9,7,1],
[6,7,3,4,1,9,5,2,8] ]
B = [ [4,2,7,9,5,1,6,8,3],
[6,3,9,2,8,4,7,5,1],
[8,5,1,7,6,3,9,2,4],
[5,1,4,8,9,6,3,7,2],
[9,7,6,4,3,2,8,1,5],
[2,8,3,1,7,5,4,9,6],
[3,9,2,6,1,8,5,4,7],
[7,4,5,3,2,9,1,6,8],
[1,6,8,5,4,7,2,3,9] ]
C = [ [9,8,5,1,3,2,4,7,6],
[2,7,3,9,4,6,5,1,8],
[4,1,6,5,7,8,9,2,3],
[1,6,7,4,8,9,2,3,5],
[8,5,2,6,1,3,7,9,4],
[3,9,4,2,5,7,8,6,1],
[7,4,1,3,9,5,6,8,2],
[5,2,9,8,6,1,3,4,7],
[6,3,8,7,2,4,1,5,9] ]
D = [ [9,8,5,1,3,2,4,7,6],
[2,9,3,9,4,6,5,1,8],
[4,1,6,5,7,8,9,2,3],
[1,6,7,4,8,9,2,3,5],
[8,5,2,6,1,3,7,9,4],
[3,9,4,2,5,7,8,6,1],
[7,4,1,3,9,5,6,8,2],
[5,2,9,8,6,1,3,4,7],
[6,3,8,7,2,4,1,5,9] ]
print("Grille A :", verif_grille(A))
print("Grille B :", verif_grille(B))
print("Grille C :", verif_grille(C))
print("Grille D :", verif_grille(D))