EXAMEN PROFESSIONNEL DE VERIFICATION D' APTITUDE AUX FONCTIONS DE PROGRAMMEUR Annee 2004 Date de l' epreuve : 03 mai 2004. Epreuve ecrite : Etablissement de l' algorithme (sous forme d' ordinogramme) correspondant il la solution probleme simple et ecriture des sequences de programme demandees un correspondantes , dans le langage C++. Duree 5 heures - coefficient 4. Avant de commencer il composer, verifiez que le sujet qui vous a ete remis comporte cinq pages (non comprise celle- ci) ; le cas echeant , signalez aux surveilants toute anomalie. Bareme de notation' Les questions 1 il 4 : 2 points; les questions 5 il 16 . 1 point par question; les questions 17 il 20 : 6 points. Nota : les questions sont independantes et peuventetre traitees non sequentiellement. .(.( Codage de Huffman document electronique il est souvent tres pratique de compresser ce document prealablement afin de diminuer le volume des donnees a transferer et sans alterer son contenu. Dans ce sujet vous allez developper une methode de compression tres efficace , appelee Pour transmettre ou stocker un codage de Huffman d' apres le nom de son inventeur. Le code de Huffman s applique principalement a la compression de donnees textuelles. Son principe est le suivant dans l' ordinateur chaque caractere de l' alphabet est represente par un chiffre variant entre 0 et 255 (le code ASaI). Ce chiffre exprime en base 2 correspond CI une serie de 8 bits. Par exemple pour le caractere ' ' on aura le code 01100001. Ainsi pour enregistrer un texte de n caracteres dans l' ordinateur on a generalement besoin de 8n bits. Le but du codage de Huffman est de reduire le nombre de bits necessaire pour chaque caractere. Plus precisement le nombre de bits necessaire va devenir une fonction de la frequence du caractere dans le texte CI compresser: plus un caractere est frequent moins il faudra de bit pour le coder. Le codage se deroule en trois phases: tout d' abord on commence par compter le nombre d' occurrences de chaque caractere , Puis en utilisant ces occurrences , on construit un arbre binaire dont les feuilles sont les caracteres ; cet arbre permet d' associer CI chaque caractere un code binaire optimal, enfin dans la troisieme etape on remplace chaque caractere dans le texte par son code optimal. Arbres binaires. Le but est de programmer une classe ((TNoeudBinaire)) representant les arbres binaires. Un arbre binaire est un arbre tel que chaque nreud a au plus deux descendants: un CI gauche et un CI droite. arbre binaire represente ci contre (fig 1) comporte 5 nreuds notes ((A , B E)) Le nreud ((A )) a deux descendants. (( B)) CI gauche et ((C)) CI droite. , D, Le nreud ((B )) a deux descendants (.(D )) a gauche et .(.(E )) a droite. nreuds .(C , D , E)) n ont aucun descendant , ce sont des feuilles. La classe .(TNoeudBinaire)) Enfin les que vous allez programmer permet de representer recursivement les arbres binaires. Chaque instance de Fig 1 : Arbre binaire )) possede quatre variables une pour le contenu du nreud ((TNoeudBinaire gauche et droite pour les deux descendants (.(TNoeudBinaire)) parent pour le nreud directement au- dessus. Par exemple pour l' arbre figure 1 le nreud (.( B)) a pour descendant gauche et droit respectivement.(.( D)) et.( E)) et pour parent le nreud .( A )) quant CI lui a pas de parent (c est la racine). deux .((TNoeudBinaire)) 1. , et enfin un Ecrire un constructeur pour la classe contenu. Ce 2. )) prenant en parametre un Object .(.(TNoeudBinaire constructeur construit un nouveau nreud contenant l' objet contenu , n ayant ni parent , ni descendant. Ecrire un constructeur pour la classe prenant en parametre un object (.(TNoeudBinaire)) gauche et droite. Ce constructeur construit contenant l' objet contenu et dont les branches gauche et droite sont respectivement gauche et droite. ))) renvoyant .(.(TNoeudBinaire)) appelant n a pas de descendants CI gauche ni CI droite. contenu et deux ((TNoeudBinaire)) .(.(TNoeudBinaire)) 3. 4. Ecrire une methode (( Ecrire une methode.(( appelant n EstUneFeuile( EstLaRacine( true ))) renvoyant.( true )) si le )) si le ((TNoeudBinaire)) a pas de parent. 1/5 .(.( ))n et un objet obj on veut savoir dans quel nreud de arbre de sommet n est contenu l' objet obj. Pour cela on applique l' algorithme suivant Etant donne une.((TNoeudBinaire Donnees' - un nreud n Resultat Le nreud de l' arbre de sommet n - un objet obj a pour valeur NULL si obJ n est pas contenu dans l' arbre de sommet dans lequel est contenu obj ou le pointeur Algorithme: - Si n contient obj alors renvoyer n - Si le descendant gauche de n n est pas NULL appliquer l' algorithme au descendant gauche de Si le resultat n est pas NULL retourner le resultat - Si le descendant droit de n n est pas NULL appliquer l' algorithme au descendant droit de n. Si le resultat n est pas NULL renvoyer le resultat. - Si non renvoyer NULL Ecrire une methode .((TNoeudBinaire * find(Object obj))) appliquant cet algorithme au nC2ud appelant. 6. La profondeur d' un nreud n est le nombre de nreud au- dessus de n dans l' arbre qui le contient. Par exemple dans l' arbre de la figure 1 , la profondeur de (.( A ) est de 0 , la profondeur de.(.( B)) et C)) est de l, Programmer une methode renvoyant la profondeur du nreud appelant de l' arbre qui le contient. ArbreBinaire avec poids Dans la suite nous aurons besoin de comparer des arbres binaires afin de pouvoir Pour cela TNoeudBinaire)) une nouvelle donnee membre poids de type entier. CompareTo)) CI la classe ((TNoeudBinaire)) nous allons ajouter a la classe 7. Ajouter une methode les trier Codage binaire des caracteres A chaque caractere correspond un nombre en base 2 comportant 8 chiffres (enparticulier la valeur representee par ce nombre est comprise entre 0 et 255). Etant donne un caractere ' ' il suffit pour obtenir le code Asar correspondant de transtyper ' en int. Une fois ce transtypage effectue , la representation binaire de ' est tout simplement egale a la representation binaire du code Asar correspondant CI ' ' Ainsi le code Asar ' i' et la representation binaire.(.( CoC1 C 2 )) sont lies par l' equation 16c3+8c4+4c5+2C6+ lc7 Developpez une methode permettant d' obtenir un caractere a partir de son code binaire. i= 128co + 64cl +32c 2+ Lecture d' une chaine de caracteres bit Etant donne une chalne de caractere , ci bit vous pouvez acceder CI n importe quel caractere de la chalne. Malheureusement pour le codage de Huffman il faut pouvoir lire la chalne de caractere bit est CI dire que chaque caractere sera lu sous forme de 8 chiffres entre 0 et a bit. 1. Pour pouvoir faire cela simplement vous allez programmer une classe.(.( TBitStringReader )) 2/5 .(.( .(.( (.( 9. Ecrire un constructeur de la classe -(.( prenant en parametre le texte TBitStringReader)) CI lire. 10. Ecrire une methode.( ))) permettant d' obtenir un a un les bits composant le ReadBit( methode renvoie le prochain bit de la chaine de caractere). Pour indiquant la position du caractere actuellement lu et une autre variable indiquant la position du prochain bit a lire. Pour texte (chaque appel CI la cela vous utilisez une variable de type entier chaque caractere la methode.(.( ))) renvoie un a un les bits composant le code ReadBit( binaire du caractere , avant de passer au caractere suivant 11. Ecrire une methode ) renvoyant vrais s il reste des bits CI lire dans le bool HasNext( texte. Ecriture d'une chaine de caractere bit el bit De la me me fac;on qu il faut pouvoir lire une chalne de caractere bit CI bit 9vant de la coder , il faut egalement pouvoir ecrire une chaine de caractere bit a bit une fois le codage effectue. Pour cela vous allez ecrire une classe.(.( TBitStringWrite La classe TBitStringWrite)) devra posseder une donnee membre de type .(( chalne )) contenant le texte dejCi code. 12. Ecrire une methode void WriteBit(int bit))) permettant d' ajouter un bit Ci la fin de la chalne de caractere. 13. Ecrire une methode.(.( ToString)) permettant d' obtenir le texte dejCl code. Codage de Huffman Dans cette partie nous allons ecrire un ensemble de methodes permettant d' effectuer le codage de Huffman CI proprement parler. 14. Ecrire une methode ou operateur .(-(int ( ))) renvoyant un tableau de 256 cases contenant le nombre d' occurrences de chaque caractere dont le code ASCIr est compris entre 0 et 255 dans le texte parametre (le nombre d' occurrences stocke dans la i- eme case du tableau renvoye). du caractere de code Asar 1 est 15. Etant donne une liste de caracteres avec leurs occurrences , on construit un arbre binaire appele .(-(arbre de Huffman)) permettant de coder ce texte , en appiiquant j; aigorithme suivant: une liste de caracteres avec leurs occurrences. RESULTAT: une liste de caracteres avec leurs occurrences. ALGORITHME: Supprimer de la liste des caracteres tous les caracteres dont le nombre occurrences est nulle. DONNEES Remplacer chaque caractere par un arbre ayant un seul nreud contenant ce caractere et dont le poids est egal au nombre d' occurrences correspondant. du caractere Tant que la liste des arbres contient au moins deux elements . Trier la liste des arbres. Remplacer les deux premiers arbres de la liste par un nouvel arbre tel que le premier element de la liste soit le descendant droit de la racine. Le 3/5 -.-----------------.---- ------- poids de ce nouvel arbre est par definition ------. -- .-. la somme des poids des deux arbres utilises dans sa construction. Le resultat est le seul arbre restant dans la liste. Ecrire une methode de la classe.(.( T )) renvoyant un )) construit en appliquant cet algorithme. ((TNoeudBinaire ArbeDeHuffman 16. Etant donne un arbre de Huffman , on associe Ci chaque feuille de l' arbre un nombre binaire appele code de Huffman. Pour cela on applique l' algorithme suivant: un nreud binaire n DONNEES. : un tableau d' entiers contenant le code de Huffman du nreud binaire n. ALGORITHME: Creer un tableau d' entiers dont la tai lie est la profondeur du nreud Creer une nouvelle variable temporaire egale Ci n Creer une variable entiere i initialisees Ci la profondeur de n Tant que temporaire n est pas la racine RESULTAT Si temporaire est le descendant gauche de son parent alors stocker dans la i- eme case de code. Sinon stocker 0 dans la i- eme case de code Reti rer 1 Ci i. Remplacer temporaire par son parent. Renvoyer le tab leau code. Ecrire une methode 0( CodeDeHuffman(TNoeudBinaire) )) renvoyant le code de Huffman du nreud parametre. Exemple : I occurence Caractere 12 III J 100 Arbre de Hufan 17 Pour coder un texte Il or Code de Hufman il suffit maintenant d' appliquer l' algorithme suivant: Compter les occurrences des caracteres dans le texte Construire l' arbre de Huffman correspondant 4/5 En utilisant la classe (( TBitStringWrite)) ecrire un nouveau texte dans lequel le code binaire de chaque caractere est remplace par son code d Huffman Ecrire une methode String Compression( String) )) realisant cet algorithme. 18. Pour decompresser un texte il faut imperativement disposer de l' arbre de Huffman ayant servi pour le codage. Dans la suite on supposera que cet arbre est un parametre de la methode. En general il faut reconstituer cet arbre CI partir des occurrences des caracteres dans le texte non compresse lesquels doivent etre enregistres au debut du texte compresse. DONNEES: une chal'ne contenant un texte code arbre de Huffman ayant servi CI coder le texte RESULTAT: Le texte decompresse ALGORITHME: Creer une nouvelle chal'ne resultat destine Ci recevoir le resultat. Cr.eer une nouvelle variable temporaire de type TNoeudBinaire )) faisant reference a Huffman il reste des bits non lus dans le texte Lire le prochain bit Tant qu Si ce bit est nul alors remplacer.(.( temporaire)) sinon le remplacer par temporaire- )droite Si temporaire)) est une feuille de l' arbre par.(.( temporaire- )o9auche qui le contient alors ajouter son contenu Ci la fin de resultat et remplacer la reference contenue dans la variable temporaire)) par une reference vers Huffman. Renvoyer resultat transforme 19. Ecrire une deuxieme version de compression et dec.ompression afin d' enregistrer les occurrences des caracteres et ainsi de ne pas avoir besoin de l' arbre de Huffman en parametre de la methode de compression. .20. Ecrire des methodes permettant de compresser et decompresser des fichiers. NOTAS : Les questions sont independantes et peuvent etre traite es non sequentiellement Vous etre libre de l' implementation du code tout en respectant la philosophie objet. Vous etes libre d'ajouter toute propriete aux classes que vous jugez utile. 5/5