TP - GPD
Transcription
TP - GPD
Université Paris 7 - Denis Diderot IF2 : Structures de données et Objets JAVA ème semestre Année 2006-2007, 2 L1 Sciences TP n◦8 Récursivité Exercice 1 Suite de Syracuse. La suite de Syracuse est dénie par la relation suivante : u0 > 0 un+1 = un /2 un+1 = 3 ∗ un + 1 Dans une classe Syracuse si si un un est pair est impair : 1. Écrire une méthode récursive public static int syracuse(int ième le n terme de la suite de Syracuse telle que u0 = init. n,int init) qui calcule 2. écrire le code suivant dans une méthode : int s, n=0; while((s = syracuse(n,init)) != 1){ System.out.println(s); n++; } Quel est le rôle de l'instruction ((s = syracuse(n,init)) != 1) ? Donnez la valeur que vous voulez à init. Quelle est la condition d'arrêt de ce programme ? Pour quelles valeurs d'entrée s'arrête-t-il ? Pouvez vous montrer qu'il s'arrête pour toutes les valeurs d'entrée ? syracuse(n+1,init), syracuse(n,init). Dénissez une méthode void syracuseStop(int terme) qui : 3. le programme précédent n'est pas optimal : en eet, lors de l'appel de on oublie que l'on a déjà calculé précédemment statique récursive ache à l'écran le terme courant. calcule le terme suivant de la suite de syracuse (en fonction du terme précédent passé en argument). s'arrête si le terme courant vaut 1 et appelle syracuseStop(termeSuivant) sinon. Testez le ensuite. 4. en fait, on sait (par des démonstrations informatiques) que pour (au moins) tout il existe un rang n tel que un = 1. La méthode que vous avez programmée termine-t-elle pour toute valeur passée en argument ? Et si les entiers sont codés sur Exercice 2 u0 < 262 , 64 bits ? Sudoku. Un principe simple de résolution d'un problème de Sudoku est : on prend la première case libre, on met le chire 1 (si cela est autorisé par les règles), puis on essaye de résoudre (récursivement, donc) le problème à partir de la case suivante. Si on n'y arrive pas, on essaye de mettre le chire 2, etc, etc. Ce principe n'est pas applicable pour un être humain, mais il marche raisonnablement bien avec les ordinateurs, car ils ont une grande puissance de calcul. Le but de cet exercice est d'écrire un programme permettant de résoudre tous les problèmes de Sudoku de taille classe Sudoku contient les objets de type Sudoku 1 : 9x9. La private de type int[][] nommé grille, qui sera de taille 9x9. Si le nombre de la case (i,j) est déjà connu (par l'initialisation), alors grille[i][j] contient ce nombre, sinon il contient 0. écrire un constructeur Sudoku(int[][] init) qui prend une grille init et la recopie dans le champ grille de l'objet. écrire une méthode String toString() qui retourne une chaîne de caractère associée à 1. chaque objet a un seul champ 2. 3. l'objet (la représentation en mode texte de la grille). Par exemple, cela pourrait être : -------+-------+------| 0 0 0 | 0 0 8 | 0 3 0 | | 7 0 0 | 0 0 0 | 0 0 5 | | 0 0 0 | 0 1 0 | 0 0 6 | |-------+-------+-------| | 0 0 9 | 0 0 5 | 0 0 2 | | 0 7 8 | 0 9 0 | 6 0 0 | | 0 4 5 | 0 0 3 | 0 0 9 | |-------+-------+-------| | 0 6 0 | 0 0 1 | 0 0 0 | | 8 0 0 | 0 6 7 | 9 0 3 | | 0 0 4 | 8 0 0 | 0 0 0 | -------+-------+------- ou bien, si l'on veut faire plus simple : 000008030 700000005 000010006 009005002 078090600 045003009 060001000 800067903 004800000 qui teste si 1 boolean nApparaitPasLigne(int nombre,int i, int j) nombre n'apparaît pas sur la ligne i entre les indices j, j+1, ..., 8. N'oubliez 4. écrire une méthode récursive pas le test d'arrêt ! Par exemple avec la grille ci-dessus, on a : nApparaitPasLigne(5,3,0): false nApparaitPasLigne(5,3,6): true nApparaitPasColonne(int nombre,int i, int j) qui teste si nombre n'apparaît pas sur la colonne j entre les indices i, ..., 8. écrire une méthode itérative boolean nApparaitPasCarre(int nombre, int i, int j) qui teste si nombre apparait dans le sous-carré de taille 3x3 associé à la case (i,j). 5. de même écrire une méthode récursive 6. Indication : le coin supérieur gauche de ce sous-carré est repéré par les coordonnées 7. 8. 1 ((i/3)*3,(j/3)*3) (pourquoi ?). écrire une méthode boolean nombrePossible(int nombre, int i, int j) qui teste s'il est possible de mettre nombre dans la case (i,j). écrire une méthode boolean caseOccupee(int i, int j) qui teste si la case (i,j) est déjà occupée. Par exemple, avec la grille précédente : jeu.caseOccupee(0,5) vaut true tandis que jeu.caseOccupee(5,0) vaut false. donc, ne contenant pas de boucle 2 9. écrire une méthode récursive boolean resolution(int i,int j) true s'il grille) et qui retourne a réussi à résoudre le problème (et dans le même temps, remplit correctement false sinon. (i,j) représente la case de départ de la résolution. L'algorithme suivi sera le suivant : test d'arrêt. calcul de la case suivante. si la case (i,j) est déjà occupée on résoud à partir de la case suivante. sinon on essaye de mettre tour à tour tous les nombres dans la case, puis de résoudre à partir de la case suivante. si rien ne marche, on remet la case à 0 et on renvoie false. 10. enn, testez vos méthodes et la résolution. 3