On va s'exercer dans ce TD, à écrire et utiliser des fonctions. Penser à chaque fois à bien vérifier la présence de la docstring (l'ajouter si elle n'y est pas !).
On rappelle dans la cellule ci-dessous une fonction que l'on a rencontré dans le TD E1 et que l'on pourra donc réutiliser après avoir exécuté la cellule:
def liste_chiffres(n : int) -> list :
""" on reçoit un entier n et la fonction renvoie
les chiffres qui composent ce nombre sous forme
d'une liste. Exemple :
liste_chiffres(377) -> [7,7,3]"""
restes = []
while n > 0 :
q = n // 10
r = n % 10
restes.append(r)
n = q
return restes
Q1. Compléter la fonction somme_cube(n : int) -> int
ci-dessous, qui reçoit un nombre entier et qui renvoie la somme des cubes des chiffres de ce nombre (Ne pas hésiter à réutiliser des fonctions créées au début du TD...).
def somme_cube(n : int) -> int:
""" reçoit un entier n et renvoie la somme des
cubes de ses chiffres. Par exemple :
somme_cube(123) -> 36 (1+8+27) """
somme = 0
# à compléter
return somme
# exemple pour tester la fonction somme_cube :
lst = [12345, 423, 202, 123]
for n in lst:
print(f"la somme des cubes des chiffres de {n} vaut {somme_cube(n)}")
Q2. Écrire ci-dessous une fonction nommée nombres_speciaux(N : int)
qui renvoie la liste de tous les nombres entiers strictement inférieurs à N et qui sont égaux à la somme des cubes de leurs chiffres. On pensera à écrire une docstring précise.
def nombres_speciaux(N : int) -> list :
# à compléter
# pour tester
print(nombres_speciaux(1000))
On rappelle deux fonctions de conversion de type du langage python (on les a utilisées à la fin du TD E1 pour calculer les produits des chiffres d'un nombre):
str(n : int)-> str # convertit un nombre en chaine de caractères
int(ch : str)-> int # convertit une chaine de caractère en nombre
Q3. Utiliser les fonctions précédentes pour ré-écrire par des manipulations de chaîne, la fonction de l'exercice 1 en une fonction somme_cube2(n : int) -> int
. On n'oubliera pas d'indiquer la docstring.
# à compléter
# pour tester la fonction somme_cube2 :
print("La somme des cubes de chiffres de 123 est ",somme_cube2(123))
print("La somme des cubes de chiffres de 11122 est ",somme_cube2(11122))
Q4. Une idée à retenir pour tester la vitesse d'exécution d'une fonction
Q4a. Exécuter la cellule suivante qui importe la fonction time()
et comprendre ce qu'elle fait en lisant l'aide donnée par la fonction help(time)
from time import time
help(time)
Help on built-in function time in module time: time(...) time() -> floating point number Return the current time in seconds since the Epoch. Fractions of a second may be present if the system clock provides them.
Q4b. Ainsi pour chronométrer une fonction il suffit de noter l'heure avant son exécution, puis l'heure après et faire la différence. À noter que l'exécution est tellement rapide, que l'on exécutera non pas une fois mais 100 000 fois la fonction à chronométrer pour pouvoir mesurer un temps !
À l'aide du script suivant on comparer la rapidité d'exécution des deux fonctions somme_cube
et somme_cube2
.
Quelle fonction semble la plus rapide ? à compléter
from time import time # on importe la fonction time() qui donne l'heure
N = 100000
t0 = time()
for i in range(N): # on répète 100000 fois l'appel à la fonction somme_cube
somme_cube(123456789)
t1 = time()
for i in range(N):
somme_cube2(123456789)
t2 = time()
print("pour cube avec divisions",t1-t0)
print("pour cube2 avec chaines",t2-t1)
Q5. Écrire une fonction multiples(base : int, max : int) -> list
dont la documentation vérifie:
def multiples(base : int, max : int) -> list :
"""
reçoit deux entiers `base` et `max` qui renvoie la liste de
tous les multiples de `base` inférieurs strictemement à `max`.
Exemple :
multiples(3,10) -> [3, 6, 9]
"""
multiples_base = []
# à compléter
return multiples_base
print(multiples(3,10))
Q6. Écrire une fonction python supprime_doublons(lst : list) -> list
qui reçoit une liste et qui renvoie une copie de cette liste où l'on a enlevé les éléments qui apparaissaient plusieurs fois. Penser à préciser la docstring...
Pour info :
elt in lst
renvoie True si elt
est dans lst
et False sinonelt not in lst
renvoie True si elt
n'est pas dans lst
et False sinondef supprime_doublons(lst : list) -> list :
"""
# à compléter
"""
lst_sans_doublons = []
# à compléter
return lst_sans_doublons
print(supprime_doublons([1,3,2,2,5,4,1,8]))
print(supprime_doublons([1,3,2,2,2,2,2,5,4,1,8]))
Q7. Écrire une fonction two_in_one(lst1,lst2) -> list
qui reçoit deux listes et qui les fusionne en une seule mais en prenant soin que chaque occurrence ne soit présente qu'une seule fois. Penser à utiliser la fonction précédente et n'oubliez pas la docstring !
def two_in_one(lst1,lst2):
# à compléter
print(two_in_one([1,2,3,4],[3,4,5,6]))
Q8. En utilisant les fonctions précédentes, écrire une fonction multiples_doubles(base1 : int, base2 : int, max : int ) -> list
dont la documentation vérifie :
def multiples_doubles(base1 : int, base2 : int, max : int ) -> list :
"""
reçoit trois entiers `base1`, `base2` et `max`, puis renvoie
la liste de tous les multiples de base1 OU de base2 inférieurs
strictement à max (attention, chaque multiple ne doit
apparaitre qu'une seule fois dans la liste).
Exemple :
multiples_doubles(3,5,10) -> [3,5,6,9]
"""
# à compléter
print(multiples_doubles(3,5,10))
None
Q9. Déterminer la somme de tous les multiples de 3 ou de 5 inférieurs strictement inférieurs à 1000 (On doit trouver 233168).
# script pour répondre à Q9
On revient sur l'exercice abordant la suite de Syracuse rencontré dans le TDB1. L'objectif est ici de structurer un peu mieux notre script en utilisant le découpage avec des fonctions. On rappelle la définition de cette suite :
« _On part d'un entier $u_0$. Si cet entier est pair on note $u_1$ la moitié de $u_0$ et s'il est impair on prend pour $u_1$ le triple de $u_0$ auquel on ajoute 1. On recommence alors le procédé avec $u_1$ pour trouver $u_2$ et ainsi de suite..._ »
En d'autres termes, si on note $(u_n)$ cette suite on a: $$ u_{n+1}=\left\{ \begin{array}{l} u_n/2 \text{ si } u_n \text{ est pair}\\ 3u_n+1 \text{ sinon}\end{array}\right. $$
Q10. Écrire une fonction python recurrence(u : int) -> int
dont la documentation vérifie:
def recurrence(u : int) -> int :
"""
La fonction reçoit un entier u qui représente le terme u(n)
de la suite de Syracuse et renvoi le terme d'indice u(n+1)
Par exemple :
recurrence(13) -> 40
recurrence(40) -> 20
"""
# à completer
return #...
Q11. On rappelle que cette suite possède la propriété (conjecture) de toujours arriver au nombre 1.
Écrire alors une fonction python syracuse_all(u0 : int) -> list
dont la documentation vérifie:
def syracuse_all(u0 : int) -> list :
"""
La fonction reçoit un entier qui represente le terme u0
de la suite.
Elle renvoie la liste de tous les termes jusqu'au premier qui vaut 1
Par exemple :
syracuse(5) -> [5,16,8,4,2,1]
"""
# à completer
return #...
Q12. En utilisant la fonction précédente, écrire les fonctions python suivantes:
syracuse_n(u0 : int, n : int) -> int
qui renvoie le n-ième terme de la suite commençant par u0.
duree_vol(u0 : int) -> int
qui renvoie la durée de vol de la suite commençant par u0 (c'est l'indice du premier terme vallant 1)
hauteur_vol(u0 : int) -> int
qui renvoie la hauteur du vol de la suite commençant par u0 (c'est la plus grande valeur obtenue par la suite commançant par u0).
Q13. Écrire une fonction python duree_max(u0_max : int) -> tuple
dont la documentation est la suivante:
def duree_max(u0_max : int) -> tuple :
"""
La fonction reçoit un entier u0_max qui représente la plus grande
valeur de u0 à tester. Elle renvoie d'une part la durée maximale
obtenue pour toutes les suites de Syracuse de premier terme u0
compris entre 1 et u0_max, et d'autre part, la valeur de u0 correspondante.
Par exemple :
duree_max(1000) -> (178,871)
"""
# à completer
return #...
Q14. Même question avec la hauteur maximale...
Pour info : les curieux peuvent avoir plein d'infos sur la suite de Syracuse en consultant par exemple le site de Gerard Villemin