corrigé
Transcription
corrigé
L2 année 2015-2016 TD 3 -POO et langage JAVA corrigé Exercice 1 : Cryptographie Polybe, un écrivain grec (205 - 126 avant JC), semble être à l'origine du premier procédé de chiffrement par substitution connu. C'est un système basé sur un carré de 25 cases, comme montré dans l'applet ci-contre. Chaque lettre peut être représentée par un groupe de 2 chiffres : celui de sa ligne et celui de sa colonne. Ainsi a=11, g=22, u=45 etc. 1 2 3 4 5 1 a f l q v 2 b g m r w 3 c h n s x 4 d i-j o t y 5 e k p u z Les cryptologues modernes ont vu dans le "carré de 25" plusieurs caractéristiques extrêmement intéressantes : La conversion de lettres en chiffres La réduction du nombre de symboles La représentation de chaque lettre par des éléments séparés. Écrire un programme en JAVA de cryptage d’un message contenu dans un tableau de N caractères alphabétiques minuscules en un message de 2N nombres compris entre 1 et 5 comme l’indique l’exemple ci-dessus. On n’oubliera pas de traiter la confusion des caractères ‘i’ et ‘j’. Proposer pour cela une convention de traitement. Écrire un programme en JAVA de décryptage d’un message contenu dans un tableau de 2N entiers en un message de N caractères alphabétiques minuscules restituant la chaîne initiale cryptée par l’algorithme précédent. (On supposera que ce tableau ne contient que des nombres compris entre 1 et 5) . public class VG { static int i,j; static final int Nmax =5; } 1/10 import java.util.*; public class Main { public static void Recherche(char c,char Cle[][]) { int trouve=0; VG.i=0; while ((trouve==0) && (VG.i<VG.Nmax)){ VG.j=0; while ((trouve==0) && (VG.j<VG.Nmax)) { if (Cle[VG.i][VG.j]==c) trouve=1; else { VG.j=VG.j+1; } } VG.i=VG.i+1; } } public static char toChar(int codeASCII) { return (char)codeASCII; } public static int toASCII(char lettre) { return (int)lettre; } public static void main(String[] args) { char Cle[][]=new char [VG.Nmax][VG.Nmax]; int i,j,k; for (i=0;i<VG.Nmax;i++) for (j=0;j<VG.Nmax;j++){ if ((i<=1)&& (j<=3)) Cle[i][j]=toChar(toASCII('a')+VG.Nmax*i+j); else Cle[i][j]=toChar(toASCII('b')+VG.Nmax*i+j); } Cle[0][4]='e'; /* Affichage de la clé */ for (i=0;i<VG.Nmax;i++){ for (j=0;j<VG.Nmax;j++) System.out.print(Cle[i][j]); System.out.println(); } char c; int msgCrypter[]= new int[200]; int LongMsg; Scanner in = new Scanner (System.in); System.out.println("\n Donnez le message à crypter : "); String msgInitial= in.nextLine(); LongMsg=msgInitial.length(); int l=0; for (k=0;k<LongMsg;k++) { c=msgInitial.charAt(k); Recherche(c,Cle); msgCrypter[l]=VG.i; msgCrypter[l+1]=VG.j+1; l=l+2; } System.out.println(" \n bonjour : voici le message crypte "); for (k=0; k<2*LongMsg;k++) System.out.print(msgCrypter[k]); System.out.println(" \n bonjour : voici le message decrypte "); for (k=0; k<2*LongMsg;k=k+2){ i=msgCrypter[k]-1; j=msgCrypter[k+1]-1; System.out.print(Cle[i][j]); } in.close(); } } 2/10 ///// pour lever l’ambigüité entre i et j on prendra le codage 2-4 pour i et 0-0 pour j public static void main(String[] args) { char Cle[][]=new char [VG.Nmax][VG.Nmax]; int i,j,k; for (i=0;i<VG.Nmax;i++) for (j=0;j<VG.Nmax;j++){ if ((i<=1)&& (j<=3)) Cle[i][j]=toChar(toASCII('a')+VG.Nmax*i+j); else Cle[i][j]=toChar(toASCII('b')+VG.Nmax*i+j); } Cle[0][4]='e'; /* Affichage de la clé */ for (i=0;i<VG.Nmax;i++){ for (j=0;j<VG.Nmax;j++) System.out.print(Cle[i][j]); System.out.println(); } char c; int msgCrypter[]= new int[200]; int LongMsg; Scanner in = new Scanner (System.in); System.out.println("\n CRYPTO 3 Donnez le message à crypter : "); String msgInitial= in.nextLine(); LongMsg=msgInitial.length(); int l=0; for (k=0;k<LongMsg;k++) { c=msgInitial.charAt(k); if(c=='j') { msgCrypter[l]=0; msgCrypter[l+1]=0; } else { Recherche(c,Cle); msgCrypter[l]=VG.i; msgCrypter[l+1]=VG.j+1; } l=l+2; } System.out.println(" \n bonjour : voici le message crypte "); for (k=0; k<2*LongMsg;k++) System.out.print(msgCrypter[k]); System.out.println(" \n bonjour : voici le message decrypte "); for (k=0; k<2*LongMsg;k=k+2){ if ((msgCrypter[k]==0)&&(msgCrypter[k+1]==0)) System.out.print("j"); else { i=msgCrypter[k]-1; j=msgCrypter[k+1]-1; System.out.print(Cle[i][j]); } } in.close(); } } 3/10 Exercice 2 : Les tours de Hanoi Étant donné trois piles, et n entiers tous différents empilés sur la première, les plus petits au dessus des plus grands : un déplacement consiste à choisir une pile A non vide, et à enlever l’entier au sommet pour le mettre au sommet d’une autre pile B, si le sommet de cette pile n’est pas un entier plus petit (sinon, le déplacement est impossible). On veut déplacer tous les entiers de la première pile sur la seconde, en se servant de la dernière. L’algorithme proposé est le suivant : Pour déplacer n entiers de la pile A sur la pile C en utilisant la pile B, on déplace (récursivement) n −1 sommets de A vers B, puis on déplace l’entier restant sur le sommet de la pile A sur la pile C, et on déplace (récursivement) n −1 sommets de B vers C. 1. Définir une classe Hanoi qui représente le jeu : ses attributs seront trois piles et le nombre d’entiers. Définissez d’ores et déjà une classe principale et une méthode main pour tester petit à petit votre travail. 2. Définir le constructeur qui initialise le jeu à partir d’un nombre d’entiers à empiler et initialise les piles dans la situation de départ. 3. Définir la méthode affiche qui affiche le contenu des trois piles sur la console. 4. Définir la méthode privée deplace et la méthode joue qui lance les déplacements. 5. Enfin, finaliser la classe principale et la méthode static main qui à partir d’un entier saisi en ligne de commande initialise et lance le jeu. 4/10 Correction : //fichier Hanoi.java public class Hanoi{ Pile depart ; Pile arrivee ; Pile intermediaire ; int nbEntiers ; public Hanoi(int nbEntiers){ this.nbEntiers=nbEntiers ; // construction des trois piles depart = new Pile(nbEntiers) ; arrivee = new Pile(nbEntiers) ; intermediaire = new Pile(nbEntiers) ; // remplissage de la pile de départ avec le premiers entiers for(int i = 0; i<nbEntiers;i++){ depart.push(i) ; } } public void affiche(){ System.out.println("Pile de depart :" + depart) ; System.out.println("Pile intermediaire :" + intermediaire) ; System.out.println("Pile d’arrivee :" + arrivee) ; } private void deplace(Pile A,Pile C,Pile B,int n){ if (n != 0) { deplace(A,B,C,n-1) ; C.push(A.pop()) ; deplace(B,C,A,n-1) ; } } public void joue(){ deplace(depart,arrivee,intermediaire,nbEntiers) ; } } //fichier JeuHanoi.java public class JeuHanoi{ public static void main(String[] argv){ Hanoi jeu = new Hanoi(4) ; jeu.affiche() ; jeu.joue() ; jeu.affiche() ; } } 5/10 Exercice 3 : Gestion de comptes bancaire Un compte bancaire peut être de 2 types (compte courant, compte rémunéré). Chaque compte est identifié par son numéro, son titulaire et la somme d’argent disponible qu’on appelle solde. Sur chaque compte bancaire, des opérations ont lieu. Il peut s’agir de retrait d’argent (on décrémente si possible le solde d’une somme donnée), le dépôt (on augmente le solde d’un montant donné) et la consultation (on retourne la somme disponible sur le compte) Dans le cas d’un solde impossible (insuffisant) on lèvera une exception de type provisionInsuffisanteErreur définie séparément. Travail à faire : Décrire la classe CompteBancaire permettant de représenter un compte. Définir un constructeur permettant de construire un compte en fixant le numéro, le titulaire et le solde initial. Écrire les méthodes suivantes : 1. deposer : qui permet de déposer un montant dans un compte 2. retirer : qui permet le retrait d’un montant d’un compte 3. afficher : qui permet d’afficher le solde d’un compte 4. virerVersement : qui permet d’effectuer un montant d’un compte vers un autre. public class Compte { String Titulaire; int Numero; double Solde; public Compte(String Titulaire, int Numero, double Solde){ this.Titulaire=Titulaire; this.Numero=Numero; this.Solde=Solde; } public void deposer(double montant){ this.Solde=this.Solde+montant; } public void retirer(double montant){ if (this.Solde<montant ) throw new provisionInsuffisanteErreur() ; else this.Solde=this.Solde-montant; } public void afficher(){ System.out.println("Le solde du compte N°"+ this.Numero+ +this.Titulaire+ " est de " + this.Solde) ; } " de " public double getSolde(){ return this.Solde; } public void virerVersement(Compte c, double montant){ c.retirer(montant); this.deposer(montant); } class provisionInsuffisanteErreur extends Error { } } 6/10 Dans un second temps, on souhaite avoir la possibilité de permettre un découvert sur un compte (un retrait conduirait à un solde négatif) ou la possibilité d’accorder une rémunération des dépôts sur un compte (compte rémunéré). Ces cas n’ont pas été prévus dans la classe CompteBancaire. Travail à faire : Définir les classes dérivées de la classe CompteBancaire permettant de représenter les comptes bancaires à découvert et les comptes bancaires rémunérés. On note qu’un compte à découvert doit avoir un découvert maximum autorisé et un compte rémunéré est défini par son taux de rémunération. Écrire la méthode fixerDecouvertMax qui permet de fixer le montant du découvert autorisé. Écrire la méthode fixerTaux qui permet de fixer le taux de rémunération Écrire la méthode retirer qui permet de retirer un montant d’un compte à découvert ou d’un compte rémunéré. public class CompteADecouvert extends Compte{ double decouvertMax; public CompteADecouvert(String Titulaire, int Numero, double Solde, double decouvertMax){ super(Titulaire,Numero, Solde); this.decouvertMax=decouvertMax; } public void fixerDecouvert(double montant){ this.decouvertMax=montant; } public void retirer(double montant){ if (this.Solde-montant<-decouvertMax ) throw new provisionInsuffisanteErreur() ; else this.Solde=this.Solde-montant; } } public class CompteRemunere extends Compte{ double Taux; double Interet; public void fixerTaux(double montant){ this.Taux=montant; } public CompteRemunere(String Titulaire,int Numero, double Solde, double montant,double Taux){ super(Titulaire,Numero, Solde); this.Interet=0.0; fixerTaux(Taux); } public void afficherCompte(){ super.afficher() ; System.out.println(" au taux de " + this.Taux) ; } } 7/10 Travail à faire : De la classe CompteRemunere, écrire la méthode afficherCompte() sachant qu’afficher les données d’un compte rémunéré revient à afficher les données d’un compte suivies du taux de rémunération. public void afficherCompte(){ super.afficher() ; System.out.println(" au taux de } " + this.Taux) ; On souhaite contrôler la validité des données saisies pour un compte bancaire ne pouvant être que de type courant, rémunéré ou joint. Travail à faire : Écrire la méthode ControleType() qui retourne à la suite de la saisie du type de compte un String valant « Courant » , « Rémunéré » ou « Joint ». private static String controleType() { char tempc ; String tempS = "courant" ; Scanner in = new Scanner(System.in) ; do { System.out.print ("Type du compte C : courant – R : rémunéré – J : joint : ") ; tempc = in.nextLine().charAt(0); } while (tempc !='C' && tempc !='R' && tempc !='J'&& tempc !='c' && tempc !='r' && tempc !='j'); switch (tempc) { case 'c' : case 'C' : tempS="Courant"; break; case 'r' : case 'R' : tempS="Rémunéré"; break; case 'J' : case 'j' : tempS="Joint"; break; } return tempS; } Travail à faire : Dans la classe Compte, sachant qu’un solde initial ne peut être négatif à la création du compte, écrire la méthode ControleValeurInit() private static Double controleValeurInit() { double tempVal ; Scanner in = new Scanner(System.in) ; do { System.out.print ("Valeur Initiale du compte : ") ; tempVal = in.nextDouble(); } while (tempVal<=0); return tempVal; } 8/10 import java.util.*; public class TestCompte { private static String controleType() { char tempc ; String tempS = "courant" ; Scanner in = new Scanner(System.in) ; do { System.out.print ("Type du compte C : courant – R : rémunéré – J : joint : ") ; tempc = in.nextLine().charAt(0); } while (tempc !='C' && tempc !='R' && tempc !='J'&& tempc !='c' && tempc !='r' && tempc !='j'); switch (tempc) { case 'c' : case 'C' : tempS="Courant"; break; case 'r' : case 'R' : tempS="Rémunéré"; break; case 'J' : case 'j' : tempS="Joint"; break; } return tempS; } private static Double controleValeurInit() { double tempVal ; Scanner in = new Scanner(System.in) ; do { System.out.print ("Valeur Initiale du compte : ") ; tempVal = in.nextDouble(); } while (tempVal<=0); return tempVal; } public static void main(String[] args) { System.out.println("Bonjour ICI Ma Banque ") ; String Message=controleType(); System.out.println("vous venez de créer un compte "+Message) ; Double SoldeInitial=controleValeurInit(); System.out.println("vous venez de créer un compte d'un solde initial de "+SoldeInitial) ; int num1 = 12345 ; int num2 = 45565 ; int num3 = 35897 ; int num4 = 26897 ; Compte c1=new Compte("HAMOUDA",num1,2000.0); Compte c2=new Compte("AMIRA",num2,500.0); Compte c3=new Compte("DURAND",num3,600.0); Compte c4; c1.afficher(); c2.afficher(); c3.afficher(); System.out.println("vous venez de déposer 600 euros sur le compte c1 ") ; c1.deposer(600); c1.afficher(); System.out.println("vous venez de retirer 50 euros sur le compte c2 ") ; c2.retirer(50); c2.afficher(); 9/10 System.out.println("vous venez de virer un versement de 60 euros du compte c3 sur le compte c1 ") ; c1.virerVersement(c3, 60); c1.afficher(); c3.afficher(); c2.retirer(80); c4= new CompteADecouvert("DUPONT",num4,2500.0,200.0); c4.virerVersement(c1, 50); c4.retirer(2800); c1.afficher(); c4.afficher(); } } 10/10