TP fait avec Mohamed Ait Ali
Récursivité : décomposition en facteurs premiers
Objectif : Ces exercices ont pour but de vous faire écrire des fonctions récursives manipulant des paramètres de type nombre. On demande donc que toutes les fonction écrites soient récursives (usage des boucles interdit). Il est également important de bien tester vos fonctions.
On cherche dans ce TP à calculer une liste représentant la décomposition en facteurs premiers d’un entier donné, c'est-à-dire son écriture sous la forme d'un produit de facteurs tels que est un nombre premier et est un entier le plus grand possible.
Par exemple, est la décomposition en facteurs premiers de .
Dans un second temps, on cherchera à optimiser les fonctions écrites.
Échauffement : recomposition et affichage
On représentera en Python la décomposition en facteurs premiers d'un nombre entier comme une liste de couples de la forme (p, e)
indiquant que le facteur apparaît dans la décomposition de . On supposera que cette liste est triée par facteurs croissants, et ne contient aucun exposant nul.
Par exemple, la décomposition de est
[(13,1)]
car est un nombre premier et , et celle de est[(2, 2), (3, 1), (5, 2)]
car .
Complétez la fonction récursive recomposition
qui étant donnée une liste sous cette forme calcule la valeur du nombre correspondant.
Complétez la fonction récursive chaine_decomp(liste_facteurs)
qui renvoie une chaîne représentant sous une forme lisible la décomposition en facteurs premiers fournie en paramètre.
Par exemple, chaine_decomp([(2, 2), (3, 1), (5, 2)])
pourrait renvoyer la chaîne "2**2 * 3 * 5**2"
.
Test de primalité
Complétez la fonction suivante, puis testez-la.
Essayez de déterminer si le nombre 64231
est premier.
Amélioration
Le nombre d'appels récursifs effectués par un appel à est_premier(n)
est de l'ordre de n
. Ceci peut poser des problèmes, comme on l'a vu dans le test précédent. Comment améliorer la fonction pour diminuer le nombre d'appels récursifs nécessaires ? Faites la modification nécessaire ci-dessus. Testez à nouveau la primalité de .
D'un premier à l'autre
À l’aide de la fonction est_premier
programmée à la section précédente, complétez la fonction ci-dessous qui calcule le plus petit nombre premier strictement supérieur à .
Par exemple,
premier_suivant(15)
renvoie 17,premier_suivant(11)
renvoie 13.
Exposant d'un facteur premier
Complétez la fonction ci-dessous qui étant donnés et renvoie l’exposant de dans la décomposition en facteurs premiers de , ainsi que le nombre restant à décomposer.
Par exemple, comme est divisible trois fois par 2 et que ,
exposant(600,2)
devra renvoyer(3,75)
, et comme 600 n’est pas divisible par 7,exposant(600,7)
devra renvoyer(0,600)
.
Décomposition
À l’aide de la fonction précédente, complétez la fonction récursive decomposition(n)
suivante, qui doit renvoyer la liste des couples représentant la décomposition en facteurs premiers de n
.
Par exemple,
decomposition(13)
renverra[(13,1)]
, etdecomposition(300)
renverra[(2, 2), (3, 1), (5, 2)]
.
Calcul du PGCD et du PPCM
Vous connaissez l'algorithme d'Euclide qui calcule le plus grand commun diviseur à deux entiers et . Cependant, si l'on connaît la décomposition en facteurs premiers de et , il est facile d'en déduire leur PGCD : en effet, la décomposition en facteurs premiers du PGCD de et contient tous les facteurs premiers communs à et , et l'exposant de chacun de ces facteurs est le minimum des exposants de ce facteur dans la décomposition de et de .
Par exemple le PGCD de et est car et .
Complétez la fonction suivante qui calcule la décomposition en facteurs premiers du PGCD de deux nombres à partir de leurs décompositions.
Compléter la fonction ppcm_decomp
suivante calculant la décomposition du PPCM de deux nombres en fonction de leurs décompositions.
Optimisation des fonctions
Les différentes fonctions réalisés lors des questions précédentes ont tendance à effectuer plusieurs fois les mêmes calculs, par exemple :
pour le test de primalité, il n'est pas nécessaire de tester le diviseur 4 si on sait que le nombre n'est pas divisible par 2 ;
pour la décomposition, si on décompose plusieurs entiers successivement, on peut être amené à tester plusieurs fois si le même entier est premier ou non, et on risque également de décomposer plusieurs fois le même nombre.
Dans la suite, nous allons utiliser une liste et un dictionnaire pour mémoriser les nombres premiers que nous rencontrons, ainsi que les décompositions déjà calculées, ceci afin d'être sûrs de ne jamais les recalculer une seconde fois.
Test de primalité optimisé
Ré-écrivons les fonctions est_premier
et premier_suivant
de sorte que l'on ne fasse que des divisions par des nombres premiers. Pour ce faire on stockera dans une liste tous les nombres premiers inférieurs à une certaine valeur.
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-72-dd65b07232e4> in <module>()
5 print(not est_premier_opti(64233, P))
6
----> 7 print(premier_suivant_opti(15, P)==17)
8 print(permier_suivant_opti(11, P)==13)
9 print(premier_suivant_opti(0, P)==2)
<ipython-input-71-7f913ed451f9> in premier_suivant_opti(n, L, indice_premier)
24 return(L[indice_premier])
25 else:
---> 26 return(premier_suivant_opti(n,L,indice_premier+1))
<ipython-input-71-7f913ed451f9> in premier_suivant_opti(n, L, indice_premier)
20 à partir de L[indice_premier] en utilisant la fonction 'est_premier_opti.
21 """
---> 22 if est_premier_opti(L[indice_premier],L, indice_premier):
23 if n < L[indice_premier]:
24 return(L[indice_premier])
IndexError: list index out of range
Calcul de décomposition optimisé
Proposer une fonction decomposition_opti
qui ne calcule pas plusieurs fois la primalité d'un même entier et qui ne calculerait qu'une fois chaque décomposition si l'utilisateur décompose plusieurs nombres.
Comparaison avec les versions précédentes
(Bonus) Pour se convaincre de l'efficacité de nos optimisations, nous allons comparer le nombre d'opérations (par exemple de divisions et calculs de reste) effectuées au total par le dernier test effectué ci-dessus. Modifiez l'ensemble des fonctions précédentes afin d'effectuer ce comptage, et comparez les résultats obtenus.