TD E3 : notion de fonctions, exercices¶

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:

In [ ]:
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

Exercice 1 : (extrait Banque PT)¶

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...).

In [ ]:
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
In [ ]:
# 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.

In [ ]:
def nombres_speciaux(N : int) -> list :
    
    # à compléter

# pour tester
print(nombres_speciaux(1000))

Exercice 2 (extrait Banque PT)¶

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.

In [ ]:
 # à 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)

In [ ]:
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

In [ ]:
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)

Exercice 3¶

Q5. Écrire une fonction multiples(base : int, max : int) -> list dont la documentation vérifie:

In [ ]:
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 :

  • la commande : elt in lst renvoie True si elt est dans lst et False sinon
  • pour la négation : elt not in lst renvoie True si elt n'est pas dans lst et False sinon
In [ ]:
def 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 !

In [ ]:
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 :

In [ ]:
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).

In [ ]:
# script pour répondre à Q9

Exercice 4¶

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:

In [ ]:
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:

In [ ]:
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:

  1. syracuse_n(u0 : int, n : int) -> int qui renvoie le n-ième terme de la suite commençant par u0.

  2. 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)

  3. 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:

In [ ]:
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...

In [ ]:
 

Pour info : les curieux peuvent avoir plein d'infos sur la suite de Syracuse en consultant par exemple le site de Gerard Villemin