Vous êtes sur la page 1sur 7

Fès – Octobre 2022 TP Python

Listes/tableaux et fonctions

Dans tout ce TP, les mots « liste » et « tableau » sont utilisés indifféremment ; il ne faut pas penser qu’un
tableau est forcément bidimensionnel. Attention, plus tard on parlera de « tableaux numpy », qui
constituent une structure de donnée légèrement différente (array).

Buts du TP

– Apprivoiser les tableaux : définition, indexation, modification, slicing...


– Manipuler un petit peu des compréhensions de liste.
– Apprendre à faire des parcours simples sur des tableaux.
– Écrire des fonctions élémentaires (ou pas !) en Python.

Exercice 1. Créer (au bon endroit) un dossier associé à ce TP. Placer dans ce dossier le fichier
cadeau.py généreusement fourni ! Vous y trouverez les parties un peu pénibles à copier dans votre script
Python (exercices 2, 5, 6) ainsi que des fonctions « clés en main » pour les exercices 21 et 34.
Lancer Spyder, sauvegarder immédiatement le fichier édité au bon endroit. Écrire une commande absurde,
de type print(5*3) dans l’éditeur, sauvegarder et exécuter.
Exercice 2. Des listes-jouet
1. Créer les listes suivantes, qui pourront servir dans la suite du TP pour vérifier les fonctions qui
auront été écrites :
l0 = [42] * 15 # Pratique mais dangereux
l00 = [42 for i in range(15)] # À privilégier, en particulier pour les listes de listes
l000 = [42 for _ in range(15)] # Possible également

l1 = [10, 30, 42, 2, 17, 5, 30, -20]


l2 = [i**2 for i in range(-3, 6)]
l3 = [i**3 for i in range(1000) if (i % 5) in {0, 2, 4}]

l4 = [841.0]
for i in range(20):
l4.append(l4[i]/3 + 28)
Ces définitions seront écrites dans le fichier de script (le .py). Après exécution (F5), on vérifiera
les valeurs de ces listes dans l’interpréteur et/ou l’explorateur de variables.
2. Quelles sont les longueurs de ces listes ?
3. Constater enfin que c’est une très mauvaise idée 1 de prendre la lettre l dans un nom de liste :-)
Exercice 3. Promettre de ne jamais appeler une liste l ou l0 mais plutôt liste ou t0... Renommer
convenablement les listes précédemment définies.
1. PEP 8, Names to Avoid :
« Never use the characters ’l’ (lowercase letter el), ’O’ (uppercase letter oh), or ’I’ (uppercase letter eye) as single
character variable names. In some fonts, these characters are indistinguishable from the numerals one and zero. When
tempted to use ’l’, use ’L’ instead. »

1
1 Manipulations des tableaux/listes ; slicing et compréhension
Exercice 4. Un peu de slicing
1. Créer la liste des dix derniers éléments de t3.
2. Créer la liste constituée des éléments de t3 sauf les 250 premiers et les 250 derniers.
3. Créer la liste constituée des cinq premiers éléments de t4 suivie des cinq derniers de cette même
liste.
Exercice 5. Éteindre l’écran. « Deviner » les valeurs des listes k,t,m,n après avoir tapé les commandes
suivantes :
k = [10, 15, 12]
t = k
m = t
n = m[:]
m[1] = 17
n[0] = 19
Allumer l’écran, et vérifier !
Plus tard, vous pourrez aller sur www.pythontutor.com/visualize.html, taper le code précédent, et
visualiser pas-à-pas l’exécution.
Exercice 6. Éteindre l’écran. « Deviner » les valeurs de t5, t6 et t7 après avoir tapé les commandes
suivantes :
t5 = [t2[2*i + 1] for i in range(3)]
t6 = [x**2 for x in t2]
t7 = [(x, y) for x in [1, 2, 3] for y in [3, 1, 4] if x != y]
Allumer l’écran, et vérifier.
Exercice 7. Créer à l’aide de compréhensions de liste 2 :
– la liste constituée des termes d’indice pair de t1 ;
– celle constituée des termes pairs de t1.
Exercice 8. Écrire une fonction réalisant l’échange de deux valeurs dans un tableau. Cette fonction
recevra comme arguments un tableau et deux indices (distincts) correspondant à des positions réelles
dans ce tableau, et effectuera l’échange sans rien renvoyer.
>>> t = [10, 42, 1, 3, 5, 7, 1515, -10]
>>> echange(t, 1, 6)
>>> t
[10, 1515, 1, 3, 5, 7, 42, -10]

2 Parcours de listes/tableaux unidimensionnels


Exercice 9. Écrire une fonction calculant la somme des éléments d’un tableau.
def somme(tab):
....
>>> somme(t1)
116
Exercice 10. Écrire une fonction calculant la moyenne des éléments d’un tableau, puis une autre cal-
culant l’ écart-type :
!1/2 ! !1/2
1 X 1 X 2 1 X 2 2
µ := x, σ := (x − µ) = x −µ
|T | |T | |T |
x∈T x∈T x∈T

2. Ou « listes en compréhension » : les deux se disent.

2
>>> moyenne(t2)
7.666666666666667
>>> ecart_type(t2)
7.803133273813083

Exercice 11. Écrire une fonction calculant le maximum des éléments d’un tableau. De même, écrire
une fonction renvoyant la position de ce maximum.
>>> maximum(t1)
42
position_maximum(t1)
2
Exercice 12. Dans la fonction écrite à l’exercice précédent, que se passe-t-il lorsque le maximum est
pris plusieurs fois ? Comment changer ce comportement ?
Exercice 13. Écrire une fonction renvoyant True si la liste donnée en argument est croissante, et False
sinon. Même chose pour cette fois la stricte décroissance.
Tester ces fonctions !
Exercice 14. Écrire une fonction prenant en entrée un tableau, et renvoyant le tableau des sommes
cumulées (depuis le premier terme) :
>>> sommes_cumulees(t2)
[9, 13, 14, 14, 15, 19, 28, 44, 69]
Évaluer le nombre d’additions réalisées, en fonction de la longueur n du tableau. Si ce nombre est de
l’ordre de n2 , réécrire la fonction pour arriver à un nombre de l’ordre de n.
Exercice 15. Écrire une fonction prenant en entrée un tableau t non vide, et renvoyant le nombre de
couples (i, j) tels que i < j et ti > tj . Complexité ?
>>> inversions([5, 1, 2, 4, 3])
5
Exercice 16. Écrire une fonction prenant en entrée un tableau t non vide, et renvoyant True si le
tableau possède un élément répété au moins deux fois, et False sinon. Complexité ?

def doublon(t):
...

>>> doublon([10, 2, 5, 2, 42])


True
>>> doublon([10, 2, 5, 3, 42])
False
Exercice 17. Écrire une fonction prenant en entrée un tableau t non vide, et renvoyant la liste (éven-
tuellement vide) des couples (i, j) tels que i < j et ti = tj . Complexité ?

def doublons(t):
...

>>> doublons([10, 2, 5, 2, 42])


[(1, 3)]
>>> doublons([10, 2, 5, 3, 42])
[]
Exercice 18. Le polynôme P = 4 − 3X + X 2 + 5X 3 peut être stocké dans un tableau de la forme
[4, −3, 1, 5]. D’une manière générale, on stocke le polynôme p0 + p1 X + ... + pn X n dans un tableau

3
de longueur n + 1 : [p0 , p1 , ..., pn ]. Pour évaluer un polynôme en un réel (c’est-à-dire calculer P (t) =
4 − 3t + t2 + 5t3 dans l’exemple précédent), on peut additionner les différents monômes :
Entrées : P, t
s ← 0 # la somme provisoire
pour i allant de 0 à |P | faire
s ← s + Pi ti
Résultat : s
1. Programmer cet algorithme dans une fonction evaluation.
def evaluation(P, t):
...

>>> evaluation([4, -3, 1, 5], 2)


42
2. En imaginant que le calcul de ti réclame i − 1 multiplications, combien de multiplications demande
l’évaluation d’un polynôme de degré d ?
On va améliorer un peu les choses, en calculant les ti « à la volée » : une variable p est chargée de
stocker les puissances successives de t : elle vaut 1 au départ, et est multipliée par t à chaque étape.
Entrées : P, t
s ← 0 # la somme provisoire
p ← 1 # la puissance de t en cours. Ici, p = t0 .
pour i allant de 0 à |P | faire
s ← s + Pi × p
p ← p × t # calcul de la puissance suivante, c’est-à-dire t1 puis t2 , etc.
Résultat : s
3. Programmer une nouvelle fonction d’évaluation utilisant cette idée.
4. Avec ce nouvel algorithme, combien de multiplications demande l’évaluation d’un polynôme de degré
d?
On propose un nouvel algorithme, basé sur l’idée suivante :

4 − 3t + t2 + 5t3 = 4 + t(−3 + t(1 + t × |{z}


5 )),
s0
| {z }
s1
| {z }
s2

ce qui permet de calculer P (t) grâce aux opérations suivantes (on effectue le calcul de l’intérieur
vers l’extérieur, pour calculer s0 puis s1 ...) :

s ← 5; s ← 1 + t × s; s ← −3 + t × s; s ← 4 + t × s.

5. Écrire l’algorithme permettant de calculer P (t) suivant cette idée, puis un dernier programme d’éva-
luation suivant cet algorithme. Il s’agit de l’algorithme de Hörner .
6. Évaluer le nombre de multiplications nécessaires pour évaluer P (t) avec cet algorithme.

>>> P0 = [4, -3, 1, 5]


>>> evaluation(P0, 2)
42
>>> evaluation_meilleure(P0, 2)
42
>>> P0.reverse()
>>> P0
[5, 1, -3, 4]
>>> horner(P0, 2)
42

4

Exercice 19. Écrire une fonction prenant en entrée un entier n > 0 et retournant la liste des nk pour
k ∈ [[0, n]].
>>> for i in range(6):
... print(ligne_binome(i))
...
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[1, 5, 10, 10, 5, 1]

3 Manipulation de tableaux bidimensionnels


Exercice 20. Expliquer ce qui suit !

>>> t1 = [[0] * 3] * 2
>>> t2 = [[0] * 3 for _ in range(2)]
>>> t1,t2
([[0, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0]])
>>> t1[1][1] = 42
>>> t2[1][1] = 42
>>> t1,t2
([[0, 42, 0], [0, 42, 0]], [[0, 0, 0], [0, 42, 0]])
Exercice 21. Les fonctions suivantes seront nécessaires à la suite du TP :
– matrice_nulle prend en entrée deux entiers (n, p) et retourne la matrice nulle de Mn,p (R).
– dimensions prend en entrée une matrice (un tableau à deux dimensions) et retourne le nombre de
lignes et le nombre de colonnes de cette matrice.
– copie réalise la copie d’une matrice.
1. Réfléchir à la façon d’écrire de telles fonctions. Éventuellement, les coder.
2. Récupérer de telles fonctions qui marchent 3 dans le fichier cadeau.py généreusement fourni.

>>> m1 = matrice_nulle(3, 2)
>>> m1
[[0, 0], [0, 0], [0, 0]]
>>> dimensions(m1)
(3, 2)
>>> m2 = copie(m1)
>>> m3 = m1
>>> m1[1][1] = 3
>>> m1
[[0, 0], [0, 3], [0, 0]]
>>> m2
[[0, 0], [0, 0], [0, 0]]
>>> m3
[[0, 0], [0, 3], [0, 0]]

Exercice 22. Écrire une fonction réalisant l’addition de deux matrices (de mêmes dimensions).
Exercice 23. Écrire une fonction réalisant la multiplication d’une matrice par un scalaire.
Exercice 24. Écrire une fonction renvoyant la transposée d’une matrice donnée en paramètre.
3. Elles...

5
Exercice 25. Écrire une fonction réalisant la multiplication de deux matrices (de dimensions compa-
tibles, c’est-à-dire de la forme (n, p) et (p, q)).
Exercice 26. Écrire une fonction réalisant le calcul de Aq , avec A ∈ Mn (R) et q ∈ N donnés. Combien
de multiplications matricielles sont réalisées pour calculer Aq ?
Exercice 27. Combien d’additions et de multiplications de réels sont nécessaires pour effectuer les calculs
des 5 derniers exercices ?
Addition Mult. scalaire Transposition Mult. matrices Calcul de Aq
Additions n×p 0 0
Multiplications 0 0
Exercice 28. Écrire une fonction testant le caractère symétrique d’une matrice (et renvoyant donc un
booléen).
>>> est_symetrique(m1)
False
>>> est_symetrique(m2)
True

4 Tri par sélection


L’objet de cette section est d’implémenter un algorithme de tri.
Informellement, il s’agit de trouver le plus grand élément d’un tableau, et le placer à la fin (et on n’y
touchera plus). On cherche ensuite le plus grand parmi ceux qui restent, et on le place à sa position
finale ; etc. Avec la notation Python des tableaux « slicés », et en notant n la taille du tableau :
– Calculer l’indice i0 du plus grand élément de t[0:n] ; échanger t[i0] et t[n-1].
– Calculer l’indice i0 du plus grand élément de t[0:n-1] ; échanger t[i0] et t[n-2].
– Calculer l’indice i0 du plus grand élément de t[0:n-2] ; échanger t[i0] et t[n-3].
– ...
– Calculer l’indice i0 du plus grand élément de t[0:2] ; échanger t[i0] et t[1].
On obtient ainsi l’algorithme assez naturel :
Entrées : T
pour j allant de n à 2 faire
Trouver un indice i0 tel que T[i0] soit maximal dans T[0:j] # donc jusqu’à j − 1 inclus...
Échanger T[i0] et T[j-1]
Il est à noter qu’un tel algorithme est destructif : le tableau passé en paramètre sera modifié (et il n’est
donc pas nécessaire de retourner quoi que ce soit.
On pourrait faire le choix de préserver le tableau passé en paramètre. Il faudrait alors faire une copie de
celui-ci, travailler sur cette copie, et retourner finalement ce nouveau tableau sur lequel on a travaillé :
Entrées : T0
Copier T0 dans un nouveau tableau T
pour j allant de n à 2 faire
Trouver un indice i0 tel que T[i0] soit maximal dans T[0:j]
Échanger T[i0] et T[j-1]
Résultat : T
Exercice 29. Simuler l’exécution de cet algorithme sur le tableau [3, 42, 112, 50, 8, -5]
On va avoir besoin de deux programmes extérieurs :
– un programme qui trouve la position du plus grand élément du début d’un tableau ;
– un autre réalisant l’échange de deux éléments.
On pourrait encapsuler ces tâches dans le programme de tri, mais c’est en général une bonne idée de
travailler de façon modulaire, en déléguant des tâches non élémentaires à d’autres programmes.
Exercice 30. Écrire une fonction prenant en entrée un tableau T et un entier k majoré par la longueur
de T , et renvoyant un indice i0 tel que T[i0] est maximal parmi T[0:k] (donc parmi les k premiers
éléments T [0], ... T [k − 1]) :

6
>>> pos_maxi_j_premiers([3, 42, -5, 8, 50, 112], 4)
1
Exercice 31. Écrire une fonction réalisant en place (sans rien renvoyer) l’échange de deux éléments
d’un tableau :
def echange(t, i, j):
...

>>> t0 = [3, 42, -5, 8, 50, 112]


>>> echange(t0, 1, 3)
>>> t0
[3, 8, -5, 42, 50, 112]
Exercice 32. Écrire un programme réalisant le tri d’un tableau. Le tri se fera obligatoirement en place,
c’est-à-dire en modifiant le tableau donné en entrée, sans rien renvoyer.
def tri(t):
...

>>> t1 = [112, 3, 42, -5, 8, 50]


>>> tri(t1)
>>> t1
[-5, 3, 8, 42, 50, 112]
Exercice 33. Évaluer, en fonction du nombre n d’éléments du tableau, la complexité (en nombre de
comparaisons) de cet algorithme de tri.
Exercice 34. Tester le programme sur des tableaux aléatoires (fonction fournie en cadeau). Évaluer éga-
lement expérimantalement la complexité avec des tests sur des tableaux dont la longueur double (comment
va alors évaluer le temps de tri ?).
Le code suivant est fourni dans le fichier cadeau.py
from time import time
temps = []

for k in range(8, 15):


t = tableau_aleatoire(2**k, 10*2**k) # pour à c viter les collisions
t0 = time()
tri(t)
t1 = time()
temps.append(t1 - t0)

rapports = [temps[i+1] / temps[i] for i in range(len(temps) - 1)]

Vous aimerez peut-être aussi