Autour de Kaprekar [th07] - Exercice Karine Zampieri, Stéphane Rivière Unisciel algoprog Version 8 janvier 2017 Table des matières 1 Algorithme de Kaprekar (18 points) 1.1 Énoncé . . . . . . . . . . . . . . . . . 1.2 Cas de trois chiffres (4 points) . . . 1.3 Le suivant de Kaprekar (8 points) . 1.4 Cas général (6 points) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 Nombre de Kaprekar (7 points) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 2 3 5 6 C++ - Autour de Kaprekar (Examen) Objectif Cet exercice décrit et réalise l’algorithme de Kaprekar et détermine les nombres de Kaprekar. Consignes : • Mots-clés : Analyse Structurée. • Durée : 2 heures • Documents : Aucun • Langage : C++ et pseudo-code • Barème : 25 points Paramètres Il est impératif de réaliser des passages par référence constant pour des tableaux et/ou structures qui ne doivent pas être modifiés. L’absence du qualificatif const induira une pénalité. Doxygen (dans le barême) Les procédures et fonctions doivent être documentés. 1 Unisciel algoprog – Autour de Kaprekar [th07] 1 1.1 2 Algorithme de Kaprekar (18 points) Énoncé Algorithme de Kaprekar Un des algorithmes (qui date des années 1949) du mathématicien Kaprekar est le suivant : 1. Prendre un entier positif. 2. Ordonner ses chiffres par ordre décroissant et par ordre croissant. 3. Soustraire les deux entiers ainsi formés. 4. Poursuivre ce processus jusqu’à ce que l’une des possibilités suivantes soit atteinte : • 0 (cas dégénéré). • Un entier constant. • Un cycle. Exemple Voici deux itérations du processus : 2213 -> 3221-1223=1998 -> 9981-1899=8082 -> etc Objectif Programmer cet algorithme pour un entier à trois chiffres et dans le cas général pour des entiers d’au plus 9 chiffres. 1.2 Cas de trois chiffres (4 points) Analyse Pour un entier à trois chiffres, l’algorithme fournit un entier constant dans les cas non dégénérés. Ainsi donc, le processus se poursuit tant que l’entier courant est différent de son prédécesseur. Pour déterminer le successeur d’un entier n, il s’agit de le décomposer en ses trois chiffres a, b, c, de les ordonner en sens décroissant (par exemple) et d’en déduire les entiers n2 (le plus grand) et n1 (le plus petit) puis d’en faire la différence. Exemple n = ==> ==> ==> ==> ==> 198 a=8, b=9, c=1 decroitre3i(a,b,c) a=9, b=8, c=1 n2 = 9*100+8*10+1 = 981 et n1 = 1*100+8*10+9 = 189 n2-n1 = 981-189 = 792 Unisciel algoprog – Autour de Kaprekar [th07] 3 (0.5 point) Écrivez une procédure permuter2i(a,b) qui échange les contenus de deux entiers a et b. (0.5 point) Écrivez une procédure decroitre2i(a,b) qui classe deux entiers a et b par ordre décroissant, c.-à-d. qu’à l’issue de la procédure, a doit contenir le plus grand entier et b le plus petit de (a,b). (0.5 point) Déduisez une procédure decroitre3i(a,b,c) qui classe trois entiers a, b et c par ordre décroissant, en appelant trois fois la procédure decroitre2i : • Classez a et b en ordre décroissant. • Puis classez b et c en ordre décroissant. • Puis classez a et b en ordre décroissant. (1 point) Déduisez une fonction kaprekarSucc3i(n) qui calcule et renvoie le suivant d’un entier n (de trois chiffres) selon l’algorithme de Kaprekar (Voir ci-avant l’analyse). Exemples : kaprekarSucc3i(198) ==> 981-189=792 kaprekarSucc3i(792) ==> 972-279=693 (0.5 point) Écrivez une fonction saisieEntier(binf,bsup) qui renvoie un entier saisi par l’utilisateur appartenant à l’intervalle d’entiers [binf..bsup]. Il faudra itérer la saisie jusqu’à ce que l’entier soit dans l’intervalle. (1 point) Enfin écrivez une procédure test_kaprekar3i qui saisit un entier à trois chiffres (donc compris entre 100 et 999) puis affiche la suite des nombres générés selon l’algorithme de Kaprekar. Exemple d’exécution : Entier dans [100..999]? 293 293 --> 693 --> 594 --> 495 --> 495 1.3 Le suivant de Kaprekar (8 points) Analyse Dans le cas général, la première opération consiste à représenter les chiffres d’un entier par un tableau d’entiers. Ainsi donc, pour calculer le suivant de Kaprekar, il convient de : 1. Décomposer l’entier n en la séquence de ses chiffres. 2. Trier cette séquence de chiffres (par exemple par ordre croissant). Unisciel algoprog – Autour de Kaprekar [th07] 4 3. Évaluer la séquence de chiffres, d’où l’entier n2 (le plus grand). 4. Renverser la séquence de chiffres. 5. Évaluer la séquence de chiffres, d’où l’entier n1 (le plus petit). 6. Retourner l’entier n2 − n1 . Exemple n = ==> ==> ==> ==> ==> ==> ==> ==> 1235648 cs=[8,4,6,5,3,2,1], nc=7 trierChiffres(cs) cs=[1,2,3,4,5,6,8], nc=7 n2 = 8654321 renverserChiffres(cs) cs=[8,6,5,4,3,2,1], nc=7 n1 = 1234568 n2-n1 = 8654321-1234568 = 7419753 (0.5 point) Définissez la constante TMAX=10 puis le type Chiffres comme étant : • Soit, une structure contenant un tableau de TMAX entiers et un entier nc représentant le nombre de chiffres effectif dans le tableau. • Soit, un vecteur dynamique d’entiers (type vector<int>). (0.5 point) Écrivez une procédure ajouterChiffre(cs,val) qui ajoute un chiffre de valeur val à la fin d’un Chiffres cs. Exemple : Soient: cs=[8,1,2,2], nc=4 Après: ajouterChiffre(cs,6) Alors: cs=[8,1,2,2,6], nc=5 (1 point) Déduisez une procédure decomposer(n,cs) qui décompose un entier positif n en ses chiffres (base 10) dans un Chiffres cs. Exemple : Pour 62218, la procédure doit initialiser cs avec [8,1,2,2,6] et l’entier nc avec 5. (1 point) Dualement, écrivez une fonction evalChiffres(cs) qui calcule et renvoie la valeur de l’entier représenté par un Chiffres cs. Exemple : Soient: cs=[8,0,2,2,6], nc=5 evalChiffres(cs) ==> 62208 (0.5 point) Écrivez une procédure afficherChiffres(cs) qui affiche un Chiffres cs en affichant chacun de ses chiffres. Unisciel algoprog – Autour de Kaprekar [th07] 5 (2 points) Écrivez une procédure trierChiffres(cs) qui classe par ordre croissant les éléments d’un Chiffres cs. Étant donné que le nombre d’éléments à trier n’est pas grand, optez pour une méthode de tri naı̈ve (à savoir en O(n2 )), au choix : sélection du maximum ou par insertion avec butoir. (0.5 point) Écrivez une procédure renverserChiffres(cs) qui renverse les éléments d’un Chiffres cs. Exemple : Soient: cs=[8,1,2,2,6], nc=5 Après: renverserChiffres(cs) Alors: cs=[6,2,2,1,8], nc=5 (1 point) Déduisez une fonction kaprekarSucc(n) qui calcule et renvoie le suivant d’un entier n selon l’algorithme de Kaprekar (cf. Analyse ci-avant). (1 point) Écrivez une procédure test_kaprekarSucc qui demande un entier puis affiche la suite des nombres générés selon l’algorithme de Kaprekar jusqu’à ce que l’utilisateur tape 0 pour spécifier qu’il veut finir. Exemple : Entier dans 1235648 --> 7419753 --> 8429652 --> 7619733 1.4 [1..999999999]? 1235648 (On continue 0==fin)? 1 (On continue 0==fin)? 1 (On continue 0==fin)? 0 Cas général (6 points) (1 point) Sachant que la longueur du cycle est d’au plus une vingtaine d’entiers pour une taille de dix chiffres, que faut-il faire pour traiter le cas général ? Écrivez votre réponse comme suit dans votre programme : /* ...ici votre réponse... */ (DOXYGEN, 5 points) Complétez votre programme selon votre analyse. Exemple d’exécution : Entier dans [1..999999999]? 1235648 1235648 --> 7419753 --> 8429652 --> 7619733 --> 8439552 --> 7509843 --> 9529641 Unisciel algoprog – Autour de Kaprekar [th07] --> --> --> --> 6 8719722 8649432 7519743 8429652 Dans cet exemple, l’entier 8429652 apparait dans la liste en tant que 5-ème élément. 2 Nombre de Kaprekar (7 points) Nombre de Kaprekar Un nombre de Kaprekar est un nombre qui, lorsqu’il est élevé au carré, peut être séparé en deux parties de tailles quasi-égales telles que la somme donne le nombre initial. Exemples 703 est un nombre de Kaprekar car 7032 = 494 209 et que 494 + 209 = 703. De même 297 car 2972 = 88 209 et 88 + 209 = 297. (3 points) Écrivez (en français) l’analyse du test. (DOXYGEN, 4 points) Complétez votre programme afin de réaliser le test (nombre de Kaprekar) et rechercher par force brute tous les nombres de Kaprekar compris entre 1 et 9999.