4.2- TP - Retour sur trace
On applique la méthode du retour sur trace (voir le cours) à deux problèmes classiques : le placement de huit reines sur un échiquier, et la résolution d'un sudoku.
I. Le problème des huit reines
On veut placer 8 reines sur un échiquier de
Comme il y a exactement une reine par ligne, on représente un placement par un tableau sol de taille 8 : sol.(i) est la colonne de la reine de la ligne i. On place les reines ligne par ligne, en commençant par la ligne 0.
Question 1
Deux reines en
Les cases d'une diagonale "descendante" vérifient
Question 2
Écrire une fonction compatible (sol : int array) (i : int) (c : int) : bool qui indique si une reine placée en ligne i, colonne c, est compatible avec les reines déjà placées dans les lignes 0 à i - 1.
Loading editor...
Question 3
Écrire une fonction récursive placer (sol : int array) (i : int) : bool qui place des reines dans les lignes i à n - 1 (où n est la taille de sol), en respectant les reines déjà placées, et renvoie true si c'est possible. Pour la ligne i, on essaie chaque colonne compatible, et on appelle placer pour la ligne suivante ; si cet appel échoue, on essaie la colonne suivante.
Loading editor...
On vous donne une fonction d'affichage :
Loading editor...
let affiche (sol : int array) : unit =
Array.iter (fun c ->
print_endline (String.concat " " (List.init (Array.length sol) (fun j -> if j = c then "♛" else "·")))) sol;;
let sol = Array.make 8 0;;
if placer sol 0 then affiche sol;;Question 4
Écrire une fonction compter (sol : int array) (i : int) : int qui compte le nombre de façons de compléter le placement à partir de la ligne i. Combien y a-t-il de solutions au problème des huit reines ? Comparer avec le nombre de façons de placer une reine par ligne,
Loading editor...
Question 5
Pour quelles valeurs de
Loading editor...
II. Le sudoku
Une grille de sudoku est représentée par une matrice int array array de taille 0. Il faut remplir les cases vides avec des chiffres de 1 à 9, de sorte que chaque ligne, chaque colonne, et chacun des neuf carrés de
Loading editor...
let grille = [| [|5; 3; 0; 0; 7; 0; 0; 0; 0|]; [|6; 0; 0; 1; 9; 5; 0; 0; 0|]; [|0; 9; 8; 0; 0; 0; 0; 6; 0|]; [|8; 0; 0; 0; 6; 0; 0; 0; 3|]; [|4; 0; 0; 8; 0; 3; 0; 0; 1|]; [|7; 0; 0; 0; 2; 0; 0; 0; 6|]; [|0; 6; 0; 0; 0; 0; 2; 8; 0|]; [|0; 0; 0; 4; 1; 9; 0; 0; 5|]; [|0; 0; 0; 0; 8; 0; 0; 7; 9|] |];; let affiche_grille (g : int array array) : unit = Array.iter (fun ligne -> print_endline (String.concat " " (Array.to_list (Array.map string_of_int ligne)))) g;; affiche_grille grille;;
Question 6
Écrire une fonction possible (g : int array array) (i : int) (j : int) (v : int) : bool qui indique si on peut écrire v dans la case (i, j) : v n'est pas déjà dans la ligne i, la colonne j, ni le carré
Indication
Le coin en haut à gauche du carré qui contient la case
Loading editor...
Question 7
On numérote les cases de 0 à 80, ligne par ligne : la case numéro resoudre (g : int array array) (k : int) : bool qui remplit la grille à partir de la case numéro k, et renvoie true si c'est possible. Si la case est déjà remplie, on passe à la suivante ; sinon, on essaie chaque chiffre possible.
Attention : si aucun chiffre ne convient, il faut vider la case avant de revenir en arrière !
Loading editor...
Question 8
Pourquoi faut-il vider la case lors du retour en arrière ? Que se passerait-il sinon ?
Si on laisse le dernier chiffre essayé dans la case, les appels suivants à possible (pour d'autres cases de la même ligne, colonne ou carré) le prendraient en compte, alors qu'il ne fait partie d'aucune solution : on éliminerait à tort des chiffres, et on pourrait conclure qu'une grille n'a pas de solution alors qu'elle en a une.
Entrez le code donné en cours pour accéder à la solution :