tome2-INFO
tome2-INFO
tome2-INFO
4 Pile et File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
4.1 Pile 65
4.1.1 Opérations de base caractérisant une Pile . . . . . . . . . . . . . . . . . . . . . . . . 66
4.1.2 Piles à capacité finie . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
4.1.3 Piles non bornées . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
4.1.4 Exercice d’application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
4.2 Files 71
4.2.1 Notion de File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
4.2.2 Opérations de base caractérisant une File . . . . . . . . . . . . . . . . . . . . . . . . 71
4.2.3 Réalisation d’une structure File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
4.3 Exercices 72
Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
Articles 127
Books 127
Misc 128
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
I
Les structures de données
linéaires
4 Pile et File . . . . . . . . . . . . . . . . . . . . . . . . . 65
4.1 Pile
4.2 Files
4.3 Exercices
1. List, tuple et str
Une structure de données est une manière de représenter les données en mémoire. Avant
de manipuler une structure, il est judicieux de préciser la manière d’attribuer une certaine
quantité de mémoire à cette structure et comment accéder à ses différentes éléments.
Pour chaque structure, il faut définir l’ensemble de ses primitives. Une primitive n’est
qu’une méthode ou une fonction qui permet de rendre un service : par exemple, on définit
une méthode qui permet d’ajouter 1 une donnée à la structure, une autre qui supprime et
ainsi de suite.
L’allocation de mémoire, c’est à dire la quantité de mémoire attribuée à la structure
de données peut être fixé au moment de sa création et ne peut pas être modifiée ; on parle
alors d’une structure de données statique. Dans d’autres cas, l’attribution est déterminée
d’une manière dynamique pendant le déroulement de l’algorithme ; on parle alors d’une
structure de données mutable.
En informatique fondamentale, il existe plusieurs structures de données, à savoir :
— Les structures de données linéaires dont l’accès à ces élément se fait via un indice.
La taille de la structure peut être dynamique(le cas des liste chaînées) comme peut
être statique(le cas de tableaux linéaire)
— Les structures de données associatives dont l’accès se fait via des clés où chaque clé
est associée à une valeur.
— Les structures de données arborescente (Les fichiers,...)
— Les structures de données relationnelles(bases des données relationnelles et les
graphes)
— Les structures de données qui suivent le paradigme Objet.
En python, la principale structure est la classe list. Il s’agit d’une structure hybride, qui
cherche à tirer d’avantage de deux structures de données classique les listes chaînées et les
tableaux.
1. et là encore, il faut spécifier la manière d’ajout : est-ce au début, au milieu ou à la fin de la structure.
10 Chapitre 1. List, tuple et str
Dans ce chapitre, nous allons étudier les structures de données linéaires (list,str, tuple)
et les différentes primitives qui permettent de rendre simple sa gestion en mémoire.
>>> a = [ ] # c e c i p e r m e t de c r é e r une l i s t e v i d e
# l i s t e d e s j o u r s de l a s e m a i n e
>>> j o u r = [ ’ Lun ’ , ’ Mar ’ , ’ Mer ’ , ’ J e u ’ , ’ Ven ’ , ’Sam ’ , ’Dim ’ ]
# l i s t e c o n t e n a n t d e s donn é e s h é t é r o g è ne
>>> E l e v e = [ ’ A l i ’ , 1 4 , ’ Imane ’ , 1 7 , ’ R a c h i d ’ , 8 ]
Comme on peut le constater, une liste peut contenir une collection hétérogène d’objets
(entiers, flottants, chaînes de caractères,autre objets). La fonction built-in len permet
renvoyer le nombre d’éléments d’une liste card(liste) = len(liste)
L’aspect linéaire de la liste se traduit par un indice (index ou offset en anglais), c’est
à dire que l’accès aux données de la structure se fait linéairement via son indice. Deux
notations existent pour l’offset en python :
1. L’offset positif : commence de 0 à n-1 où n = len(liste).
2. L’offset négatif : commence de -n à -1.
Ainsi, pour accéder à l’élément d’indice i, il suffit d’utiliser la syntaxe suivante :
nom_liste [ i ]
>>> j o u r [ 2 ]
’ Mer ’
>>> E l e v e [ − 3 ]
14
Une liste en python est mutable c’est à dire, il est possible de modifier sa structure par :
— l’ajout d’un élément :
>>> E l e v e = E l e v e + [ 9 , ’ I b t i s s a m ’ , 1 1 ] # A j o u t à l a f i n
>>> E l e v e
[ ’ A l i ’ , 1 4 , ’ Imane ’ , 1 7 , ’ R a c h i d ’ , 8 , 9 , ’ I b t i s s a m ’ , 1 1 ]
>>> d e l ( E l e v e [ 6 ] )
>>> E l e v e
[ ’ A l i ’ , 1 4 , ’ Imane ’ , 1 7 , ’ R a c h i d ’ , 8 , ’ I b t i s s a m ’ , 1 1 ]
>>>a [ 5 : ] = ’ S i n g e s ’
>>>a
[ 1 , 2 , ’ abc ’ , ’ S ing es ’ ]
Généralement, ses opérateurs sont définies dans la classe list à l’aide d’un mécanisme
appelé : surcharge ou polymorphisme 2 et sont accessible via les méthodes déclarées avec la
syntaxe suivante : __methode__ . Par exemple, le comportement de l’opérateur d’addition
+ qui est utilisé comme un opérateur de concaténation pour les listes est défini grâce à la
méthode surchargée __add__.
Le tableau qui suit donne une liste non exhaustive des opérateurs définis dans la classe
list :
2. On traitera ces concepts dans un chapitre consacré à la programmation orientée objet POO
14 Chapitre 1. List, tuple et str
TABLE 1.1 – Opérateurs de base pour manipuler des objets de type list
1.1 Les listes : List 15
maListe.maMthode(paramtres)
Dans le tableaux qui suit, on donne un ensemble de méthodes qui sont propres à la classe
list :
Méthode Description
append(e) ajoute de e à la fin d’une liste
insert(i,e) Elle insère e à la position(index) i dans une liste et
renvoie None en cas de succès et erreur en cas d’un
index hors sa plage des indices
extend(iterable) étendre une liste par l’ajout à la fin des éléments
d’un objet itérable
remove(e) supprime la première occurrence de e dans la liste.
Elle retourne None en cas de succès et erreur si e
n’existe pas dans la liste
pop() retourne le dernier élément d’une liste et supprime
celui-ci
pop(i) retourne l’élément d’indice i d’une liste et supprime
celui-ci. Elle renvoie une erreur en cas de i est "in-
dex out of range"
sort() trie la liste par ordre croissant. Elle possède un pa-
ramètre nommé reverse de valeur par défaut false.
sort(reverse=True) donne un tri par ordre décrois-
sant
reverse() inverse l’ordre d’une liste
count(valeur) renvoie le nombre d’occurrence d’une valeur dans
la liste
TABLE 1.2 – Quelques méthodes utiles pour manipuler une liste
>>>a = [ 1 , 2 , 3 ]
>>>a . a p p e n d ( 5 ) # [1 ,2 ,3 ,5]
>>>a . a p p e n d ( [ 7 , 8 ] ) # [1 ,2 ,3 ,5 ,[7 ,8]]
>>>a . i n s e r t ( 1 , ’ ok ’ ) # [ 1 , ’ ok ’ , 2 , 3 , 5 , [ 7 , 8 ] ]
>>>a . e x t e n d ( [ ’ a ’ , ’ b ’ , ’ c ’ ] ) # [ 1 , ’ ok ’ , 2 , 3 , 5 , [ 7 , 8 ] , ’ a ’ , ’ b ’ , ’ c ’ ]
>>>a . remove ( [ 7 , 8 ] ) # [ 1 , ’ ok ’ , 2 , 3 , 5 , ’ a ’ , ’ b ’ , ’ c ’ ]
>>>a . pop ( ) # [ 1 , ’ ok ’ , 2 , 3 , 5 , ’ a ’ , ’ b ’ ]
>>>a . pop ( 1 ) # [1 ,2 ,3 ,5 , ’ a ’ , ’ b ’]
>>>a . s o r t ( ) # r e n v o i e None e t t r i l a l i s t e : [ 1 , 2 , 3 , 5 , ’ a
’ , ’ b ’]
16 Chapitre 1. List, tuple et str
>>>a . r e v e r s e ( ) # r e n v o i e None e t i n v e r s e s e s é l é m e n t s
>>>a . i n s e r t ( 4 , ’ a ’ ) # renvoie :[ ’ b ’ , ’ a ’ ,1 ,2 , ’ a ’ ,3 ,5]
>>>a . c o u n t ( ’ a ’ ) # renvoie l ’ entier 2
Un des avantages des structures de données linéaire est qu’on peut parcourir ses éléments
à l’aide d’un indice. On peut parcourir les éléments d’une liste élément par élément via la
boucle for :
— parcours par l’indice :
for x in range ( len ( l i s t e ) ) :
p r i n t ( " é l é ment d ’ i n d i c e {} e s t {} " . $ f o r m a t ( x , l i s t e [ x ] ) )
Pour l’instant, les seules structures mutables que l’on connaisse sont les listes
R Les types int, long, float, bool, complex et str ne sont pas des objets mutables
1.1 Les listes : List 17
>>>a = [ 7 , 2 , 9 ]
>>>b=a
>>> i d ( a ) == i d ( b ) # r e n v o i e True
>>>b . a p p e n d ( 5 )
>>>a
[7 ,2 ,9 ,5]
>>>b
[7 ,2 ,9 ,5]
>>>c=a [ : ]
>>>c . a p p e n d ( ’ a b c ’ )
>>>a = [ [ 1 , 2 , 3 ] , [ 4 , 5 , 6 ] , [ 7 , 8 , 9 ] ]
>>>b=a [ : ]
>>> i d ( a ) == i d ( b ) # Renvoie F a l s e
>>> i d ( a [ 1 ] ) == i d ( b [ 1 ] ) # R e n v o i e T r u e
Nous constatons sur cet exemple que nous n’avons pas réalisé une copie de première ni-
veau : a et b référencent effectivement deux emplacement de mémoire tandis que a[i] et b[i]
référencent le même objet mutable et toute modification de l’un entraîne une modification
identique de l’autre :
1.2 Les n-uplets : tuple 19
>>> e1 = ( 1 , 0 , 0 )
>>> e1
(1 ,0 ,0)
>>> e1 [ 0 ]
1
>>> e [ 1 ] = 3 # r e n v o i e une e r r e u r
20 Chapitre 1. List, tuple et str
Une conséquence immédiate de l’aspect immuable est qu’on ne peut pas appliquer les
méthodes append, insert, pop, remove, sort, extend et clear car elles modifient la structures.
Les seules méthodes qu’on peut appliquer sont, donc, count et index qui renvoient respecti-
vement le nombre d’occurrences d’un élément et l’indice d’un élément dans la structure
s’il existe :
>>> e2 = ( 0 , 1 , 0 )
>>> e1 . c o u n t ( 2 )
2
>>> e2 . i n d e x ( 1 )
1
Cependant, si un élément est mutable alors on peut modifier sa structure. Cela affecte
seulement l’élément en question et non plus la structure dans laquelle est inclue :
>>> n o t e s = ( ’ A l i ’ , [ 1 2 , 1 5 ] , ’ Imane ’ , [ 8 . 5 0 , 1 6 ] )
>>> n o t e s
( ’ A l i ’ , [ 1 2 , 1 5 ] , ’ Imane ’ , [ 8 . 5 , 1 6 ] )
>>> n o t e s [ 1 ] . a p p e n d ( 1 3 )
>>> n o t e s
( ’ A l i ’ , [ 1 2 , 1 5 , 1 3 ] , ’ Imane ’ , [ 8 . 5 , 1 6 ] )
>>>
Listing 1.19 – modification d’un objet mutable dans uns structure non mutable
Les opérateurs définis dans le tableau table1 de la deuxième section de ce chapitre pour les
listes sont aussi valide pour les tuples :
>>> ’ A l i ’ i n n o t e s
True
>>> e1 > e2
True
>>> n o t e s [ 2 : ]
( ’ Imane ’ , [ 8 . 5 0 , 1 6 ] )
>>>
>>> a = 2
>>> b = 7
>>> a , b = b , a
>>>a
7
>>> b
2
>>>
Si on ne spécifie pas les délimiteurs lors d’affectation d’un ensemble de valeurs à une
variable, python le prend par défaut comme un tuple :
>>> x = 1 , 2
>>> x
(1 , 2)
Cependant, si on veut définir un tuple contenant un seul élément, il faut ajouter une virgule
à la fin :
>>> y = ( 3 , )
>>> y
(3 ,)
>>> t y p e ( y )
< ’ class ’ , tuple >
>>> z = ( 3 )
>>> z
3
>>> t y p e ( z )
<’ class ’ , int >
Si l’échange fonctionne bien pour les objets de type int, il fonctionne aussi parfaitement
bien pour les autres objets immuable : bool, float, str, tuple :
>>> e2 = 1 , 0 , 0
>>> e1 = 0 , 1 , 0
>>> e1 , e2 = e2 , e1
>>> e1
(1 , 0 , 0)
>>> e2
$ (0 , 1 , 0)
$>>>
>>> s = ’ He i s a man ’
>>>c= " He ’ s \ a \ man "
>>> l = " " " I l a d i t : " b o n j o u r " " " "
>>> t y p e ( s )
< ’ c l a s s ’ , ’ s t r ’>
— \n : en un saut de ligne
— \t : en une tabulation
— \b : en un backspace
— \a : en un bip
— \’ : en un ’ (apostrophe), mais il ne ferme pas la chaîne de caractères
— \" : en un "(guillemet), mais il ne ferme pas la chaîne de caractères
— \\ : en un \ (Antislash)
>>> s = ’ He \ ’ s \ t a man ’
" He ’ a man "
Symbole Signification
%d Formater une valeur entière
%f Formater une valeur réelle
%s Formater une valeur textuelle
%o Formater une valeur octale
%x Formater une valeur hexadécimale
1.4 Exercices[10]
→
−
Exercise 1.3 On représente un vecteur par un tuple. Par exemple, le vecteur U (x1 , x2 , x3 , x4 , x5 )
est représenté par un tuple U = (x1 , x2 , x3 , x4 , x5 )
1. Écrire un programme qui réalise l’addition de deux vecteurs U et V de même
dimension n
2. Écrire un programme qui réalise le produit scalaire de deux vecteurs U et V de
même dimension n
3. Écrire un programme qui réalise le produit vectoriel de deux vecteurs U et V de
même dimension n
■
26 Chapitre 1. List, tuple et str
Exercise 1.4 On vous propose dans cet exercice de programmer les fonctions suivantes :
1. est_lettre(e) qui prend en paramètre une lettre et qui renvoie True si e est une
lettre. Par exemple, est_lettre(’r’) rendra True alors que est_lettre(’ !’) rendra
False.
2. nbrMot qui prend en entrée une chaîne de caractères, et rend le nombre de mots
de cette chaîne. Par exemple, nbrMot(’Cette chaîne est longue, elle contient huit
mots’) rendra 8.
3. est_phrase qui détecte si une chaîne de caractères est une phrase ou non. On
considère que les chaînes de caractères analysés sont constituées au plus d’une
phrase.
■
Exercise 1.5 Un palindrome est une entité qui se lit de la même façon de gauche à
droite et de droite à gauche. Par exemple, ’laval’ est un mot palindrome. De même, ’la
mariée ira mal’ est une phrase palindrome. Concernant les nombres, ’12321’ est aussi
un palindrome.
Écrire une fonction python qui renvoi True si le mot passé en argument est palin-
drome et False sinon. ■
altitude ==> a l t i t u d e
et123 ==> e t 1 2 3
3. Écrivez un code qui définit une fonction indiceMaximum(lt) qui renvoie l’indice
du maximum d’une liste numérique lt (non vide), c-à-d. qu’elle effectue la même
action que : lt.index(max(lt)). Jeux de tests :
4. Écrivez un code qui définit une fonction nbrOccurs(lt,e) qui calcule et renvoie le
nombre de fois qu’un élément e apparaît dans une liste lt, et -1 si lt n’a pas le bon
type. Jeux de tests :
nbroccurs(["a",1,2,3,2,2,5,2],2) ==> 4
nbrOccurs(2,2) ==> -1
nbroccurs(["a",1,2,3,2,2,5,2],9) ==> 0
1.4 Exercices[10] 27
5. Écrivez un code qui définit une fonction unique(lt) qui calcule et renvoie la liste
sans recopie des doublons d’une list lt. Jeux de tests :
1 2 9 7 3 4 2 3 5 6 7 3 4 1 8 9 ==> [1, 2, 9, 7, 3, 4, 5, 6, 8]
"a" 1 2 3 2 2 5 2.0 ==> [’a’, 1, 2, 3, 5]
"ab" "bb" "c" "C" "ab" ==> [’ab’, ’bb’, ’c’, ’C’]
6. Écrivez un code qui définit une fonction lchiffres(n) qui renvoie la liste des
chiffres (du poids faible au poids fort) d’un entier positif n. Jeux de tests :
7. Écrivez un code qui définit une fonction lfibonacci(n) qui, pour un entier positif
n, calcule et renvoie la liste des n premiers termes de la suite de Fibonacci :
u0 = 0, u1 = 1
et
∀n ∈ N, un+2 = un+1 + un .
Jeux de tests :
16 ==> [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]
0 ==> []
1 ==> [0]
2 ==> [0, 1]
3 ==> [0, 1, 1]
k=n k
x
P(x) = ∑ k! = a0 + a1x + a2x2 + ... + anxn
k=0
où les coefficients ak ∈ R.
Le type Polynôme n’existe pas en python et pour travailler avec les polynômes, on
utilisera un astuce simple : on pourrait stocker les coefficients ak dans une liste LP tels que
pour chaque indice k de la liste LP, ak est stocké à l’indice k : LP = [a0 , a1 , a2 , ..., an ].
Par exemple, si P(x) = −4x7 + 3.5x5 − x2 + 1 alors la liste associée à P serait :
indice 0 1 2 3 4 5 6 7
Monôme a0 x 0 a1 x 1 a2 x2 a3 x 3 a4 x 4 a5 x5 a6 x 6 a7 x 7
coefficient 1 0 -1 0 0 3.5 0 -4
Dans la suite de ce problème, on adoptera cette forme de représentation afin d’écrire un
ensemble de fonctions nécessaires pour gérer les polynômes à coefficients dans R.
k=n
xk
1. Construire, à la main, la liste associée au polynôme P(x) = ∑ k! Pour n = 5.
k=0
Réciproquement, donner le polynôme associée à la liste [−2, 3, 0, 0, 1, −1, −1, 2].
2. Écrire une fonction generate(n : int)-> list , d’argument un entier n et qui renvoie
k=n
xk
la liste associée au polynôme P(x) = ∑ k! .
k=0
3. Écrire une fonction toString(LP : list)-> str , d’argument une liste associée au
polynôme P et qui renvoie une représentation textuelle sous forme d’une chaîne de
caractères S=’an Xˆ n + an−1 Xˆ n-1...+a1 X + a0 ’.
Par exemple :
4. Écrire une fonction value(LP : list, a : float)-> float , d’argument une liste LP asso-
ciée au polynôme P, un nombre réel a et qui renvoie la valeur P(a) qui évaluer P en a
Par exemple :
6. Écrire une fonction scale(LP : list, k : float)-> list , d’argument une liste LP asso-
ciée au polynôme P, un nombre réel k et qui renvoie une list associée au polynôme
(kP)(x) = kP(x) Par exemple :
7. Écrire une fonction add(LP : list, LQ : list)-> list , d’argument une liste LP asso-
ciée au polynôme P, une liste LQ associée au polynôme Q et qui renvoie une list
associée au polynôme (P + Q)(x) = P(x) + Q(x) Par exemple :
8. Écrire une fonction sub(LP : list, LQ : list)-> list , d’argument une liste LP associée
au polynôme P, une liste LQ associée au polynôme Q et qui renvoie une list associée
au polynôme (P − Q)(x) = P(x) − Q(x) Par exemple :
9. Écrire une fonction mult(LP : list, LQ : list)-> list , d’argument une liste LP asso-
ciée au polynôme P, une liste LQ associée au polynôme Q et qui renvoie une list
associée au polynôme (P × Q)(x) = P(x) × Q(x) Par exemple :
10. Écrire une fonction derived(LP : list)-> list , d’argument une liste LP associée au
polynôme P et qui renvoie une list associée au dérivée de la fonction polynôme
(P)(x) Par exemple :
Question 1 :
Écrivez les instructions permettant de fixer le format 3 × 12. Une fonction en python,
est-elle autorisée d’accéder aux valeurs N et P ?
Question 2 :
Écrivez la fonction générer_tab ( ) sans paramètres qui génère un tableau tab de taille
P(tab est donc de dimension 1) avec les entiers aléatoires dans [1, 20] et qui renvoie tab
Question 3 :
Écrivez la fonction remplir_tab ( ) sans paramètres qui remplit le tableau tab de format
N × P avec les entiers aléatoires dans [1, 20] et affiche son contenu à l’écran, sous forme
d’un rectangle de nombres de N lignes et de P colonnes. La fonction renvoie le tableau tab
(on pourra utiliser la fonction générer_tab () )
Question 4 :
Écrivez la fonction somme_ligne(lig, t) qui calcule , affiche et renvoie la somme des
éléments de la ligne lig du tableau t de taille N × P
Question 5 :
Écrivez la fonction somme_ligne_max(t) qui :
1. affiche la somme des éléments de chaque ligne du tableau t de taille N × P (en
appelant la fonction précédentes) ;
2. calcule et renvoie la somme maximale obtenu sur une ligne du tableau t.
Question 6 :
On désire chercher sur chaque ligne de la liste, les séquences (slices) de deux éléments
supérieurs à une valeur donnée (c’est-à-dire deux éléments consécutifs supérieur à cette
valeur).
Écrivez la fonction sequence_deux_elements_sup (t, val) qui, pour chaque ligne, affiche
les indices j de t où se trouvent deux éléments consécutifs dont la valeur est supérieur à val.
L’affichage se fera sous forme intervalle [j, j+1] ; comme dans l’exemple ci-dessous.
Question 7 :
Écrivez la fonction teste qui, en appelant les fonctions précédentes :
1. remplit la liste d’entiers aléatoires de [1, 20] et en affiche le contenu à l’écran ;
2. calcule et affiche la somme des éléments de chaque ligne, puis la somme maximale ;
3. pour chaque ligne, affiche les séquences de deux éléments supérieurs à 12
Exemple d’affichage obtenu à l’écran par l’exécution du programme :
1.4 Exercices[10] 31
Question 8
Généralisez la fonction de la question 6, pour afficher les séquences d’éléments de
valeurs supérieure à val, quelle que soit leur longueur (un élément, ou deux, ou trois, etc.)
Par exemple, si l’on prend l’exemple ci-dessus, on obtiendra :
sequence d’éléments supérieurs à 8 :
ligne 0 : intervalle[0,0] ; intervalle[2,2] ; intervalle[4, 7] ; intervalle[9,9] ;
ligne 1 : intervalle[0, 2] ; intervalle[4, 6] ; intervalle[10,10] ;
ligne 2 : intervalle[2,6] ; intervalle[8,8] ; intervalle[10,10] ;
Définissez la constante TMAX= 100 (nombre maximal de cases d’une liste). Dans la
suite de problème, le type ENTList définit une liste de TMAX entiers et le type LCarre est
équivalent au type ENTList.
Par exemple la liste suivante [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]] sera
32 Chapitre 1. List, tuple et str
optimisée par la liste [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
Algorithme
L’algorithme ci-après ne fonctionne que si n est impair.
Il place les nombres dans l’ordre 1, 2, ..., n2 .
— Placez le 1 dans la case située une ligne en dessous de la case centrale.
— Après avoir placé k dans une case de coordonnées (i, j), placez k + 1 dans la case (l,
c) = (i + 1, j + 1), en défilant au-delà des bordures, c.-à-d. que si la case dépasse la
dernière ligne (resp. la dernière colonne), la case sélectionnée est celle en première
ligne (resp. en première colonne). En cas d’occupation d’une case, la case suivante
est (l, c) = (i + 2, j). Par construction, on démontre que cette case n’est pas occupée.
— Exemple : Voici le carré d’ordre 3 obtenu à l’aide de cette méthode.
816
357
492
6. Déroulez l’algorithme sur le carré d’ordre 3 et vérifiez que vous obtenez celui de
l’exemple.
7. Écrivez une fonction suivant(k,n) qui renvoie le suivant de l’entier k dans l’ensemble
circulaire [1..n] .
8. De même, écrivez une fonction precedent(k,n) qui renvoie le précédent de l’entier k
dans l’ensemble circulaire [1..n] .
9. Écrivez alors une procédure creerCMagique1(c,n) qui crée le carré magique d’ordre
n dans un LCarre c selon l’algorithme ci-dessus.
10. Écrivez un script de sorte qu’il :
— Saisit l’ordre du carré dans un entier (par exemple n ).
— Déclare un TCarre (par exemple c ).
— Construit le TCarre magique d’ordre n dans c .
— Enfin affiche c .
11. Testez. (Pour n = 3 et n = 5)
8 1 6 17 24 1 8 15
3 5 7 23 5 7 14 16
4 9 2 4 6 13 20 22
10 12 19 21 3
11 18 25 2 9
1.4 Exercices[10] 33
2. Algorithmes de tri et de recherche
2.1 Présentation
Principe
Algorithme
Parcourir une liste à l’aide d’une boucle while ou for et à chaque itération i (une tour
de la boucle) on vérifie si l’élément d’indice i coïncide avec l’élément recherché ; si c’est
le cas alors on retourne cet indice i. Si on a pas sorti avec cet indice alors on retourne None
ou un message d’erreur.
36 Chapitre 2. Algorithmes de tri et de recherche
Programme
L’implémentation python de cet algorithme est immédiate :
Notons qu’une fonction en python renvoie par défaut la valeur None si aucun renvoi
n’est pas défini. Une fois la fonction recherche(liste, data) n’a pas renvoyé l’index k alors
après while, elle retourne la valeur None.
Algorithme
Étant donné une liste L de taille n et une donnée data qu’on veut rechercher son indice
dans L. On suppose que les éléments de la liste sont triés en ordre croissant.
L’intervalle initial de recherche est [a, b] avec a=0 et b=len(liste) -1. Tant que [a, b] est
un intervalle c’est à dire a ≤ b alors on calcule c l’indice du centre et on compare l’élément
d’indice c avec data. Trois cas, donc, sont envisageables :
— Si L[c]= data alors on retourne l’indice i
— Si L[c] < data alors on lance la recherche dans l’intervalle [c+1, b] (remarquons ici
que la seule valeur modifiée est celle de la variable a)
— Si L[c] > data alors on lance la recherche dans l’intervalle [a, c-1] (b = c-1)
2.3 Algorithmes de tri 37
Programme
Voici une implémentation python de l’algorithme précédente :
Principe
Le principe de tri à bulle (ou encore par propagation) consiste à parcourir plusieurs
fois une liste, comparer deux à deux des éléments adjacents et échange s’ils ne sont pas
ordonnés. Le processus de parcours s’arrête lorsqu’on parcours la liste sans faire d’échange.
Par exemple, considérons la liste l = [5, 3, 7, 2, 8, 4] de taille n = 6 :
3 5 7 2 8 4
3 5 7 2 8 4
— Itération 1 : 5 3 7 2 8 4 3 5 2 7 8 4
3 5 2 7 8 4
3 5 2 7 4 8
3 5 2 7 4 8
3 2 5 7 4 8
— Itération 2 : 3 5 2 7 4 8 3 2 5 7 4 8
3 2 5 4 7 8
3 2 5 4 7 8
2 3 5 4 7 8
2 3 5 4 7 8
— Itération 3 : 3 2 5 4 7 8 2 3 4 5 7 8
2 3 4 5 7 8
2 3 4 5 7 8
Algorithme
Programme
On donne ici deux implémentations possible de cet algorithme : La première variante
est une traduction directe de l’algorithme précédente :
def t r i _ b u l l e ( l i s t e ) :
n = len ( l i s t e )
echange = True
while echange :
echange = False
k = 0
while k < n −1:
i f l i s t e [k] > l i s t e [k +1]:
l i s t e [ k ] , l i s t e [ k +1] = l i s t e [ k +1] , l i s t e [ k ]
echange = True
k = k + 1
Notons que la fonction ne renvoie aucune valeur car la liste passée en argument est
modifié par un algorithme de tri en place et notre liste se trouve triée par ordre croissant à
la fin de l’algorithme.
La deuxième variante est une conséquence immédiate de tri à bulle : à chaque itération,
les plus grandes valeurs sont placées à la fin et les petites valeurs se "remontent" au début
de la liste comme les bulles d’un liquide les plus "légers" remontent le plus rapidement à
sa surface :
def t r i _ b u l l e ( l i s t e ) :
n = len ( l i s t e )
f o r i i n range ( n −1) :
f o r k i n r a n g e ( n− i − 1 ) :
i f l i s t e [k] > l i s t e [k +1]:
l i s t e [ k ] , l i s t e [ k +1] = l i s t e [ k +1] , l i s t e [ k ]
— liste initiale : 5 3 7 2 8 4
— Itération 1 : 5 3 7 2 8 4 =⇒ 2 3 7 5 8 4
— Itération 2 : 2 3 7 5 8 4 =⇒ 2 3 7 5 8 4
— Itération 3 : 2 3 7 5 8 4 =⇒ 2 3 4 5 8 7
— Itération 4 : 2 3 4 5 8 7 =⇒ 2 3 4 5 8 7
— Itération 5 : 2 3 4 5 8 7 =⇒ 2 3 4 5 7 8
— liste finale : 2 3 4 5 7 8
Algorithme
Nous donnons tout d’abord l’algorithme qui permet de sélectionner l’indice de plus
petit élément d’une liste entre l’indice i et la fin de la liste. On applique, donc, le principe
mathématique de Min(E) :
m∈E
m = Min(E) ⇔
∀x ∈ E, m ≤ x
Programme
Voici une implémentation python des algorithmes de recherche du minimum (getIndex-
Min) et de tri par sélection (selection_sort) :
def getIndexMin (L , i ) :
n = len (L)
m = i
f o r k i n r a n g e ( i +1 , n ) :
i f L [m] > L [ k ] :
m = k
return m
def s e l e c t i o n _ s o r t (L) :
n = len (L)
for i in range ( n ) :
m = getIndexMin (L , i )
i f m != i :
L [ i ] , L [m] = L [m] , L [ i ]
Algorithme
[6] Pour insérer un élément d’indice i dans sa place parmi les i premiers éléments
on procède par un décalage à droite de ses éléments jusqu’à l’élément qu’on a pris soit
supérieur à T[j-1] ou j ≤ 0 sachant que l’élément retiré est T[i] qu’on nomme par carte :
42 Chapitre 2. Algorithmes de tri et de recherche
Programme
On traduit instruction par instruction l’algorithme précédente et on obtient en python
le code qui suit :
def i n s e r t i o n _ s o r t (T) :
n = len (T)
for i in range (1 , n ) :
c a r t e = T[ i ]
j = i
w h i l e j >0 and c a r t e < T [ j − 1 ] :
T[ j ] = T[ j −1]
j = j −1
T[ j ] = c a r t e
2.4 Exercices
2.4.1 Exercice 1
1. Concevez un algorithme de recherche du maximum dans un ensemble à n éléments.
2. Nous supposerons ici que l’ensemble considéré ne contient pas deux fois la même
valeur. Proposez un algorithme simple de recherche du deuxième plus grand élément
2.4.2 Exercice 2
1. Construire trois listes de 10000 entiers : liste1 contient les entiers de 1 à 10000
rangés dans l’ordre croissant ; liste2 contient les entiers de 10000 à 1 rangés dans
l’ordre décroissant ; liste3 contient 10000 entiers choisis de manière aléatoire avec la
fonction randint parmi les entiers de 1 à 10000 bornes comprises.
2.4 Exercices 43
2. Mesurer le temps d’exécution des trois algorithmes de tri (tri par insertion, tri à
bulle, tri par sélection) pour trier chacune des trois listes précédentes. On utilisera la
fonction time du module time. Par exemple :
from time import time
debut=time ( )
tri_insertion ( liste1 )
fin = time ( )
print ( debut - fin )
3. Mesurer sur les mêmes listes le temps d’exécution des algorithmes de tris utilisés
par la fonction sorted et par la méthode sort(). La syntaxe est "sorted(iste)" et
"liste.sort()".
4. Mesurer maintenant le temps d’exécution de la fonction sorted et de la méthode
sort()sur une liste de 100000 entiers choisis de manière aléatoire avec la fonction
randint parmi les entiers de 1 à 10000 bornes comprises.
2.4.3 Exercice 3
L’objectif est d’écrire un programme qui trie une liste de mots et les range dans l’ordre
lexicographique (ordre des dictionnaires).
1. Écrire la définition de la variable "alphabet" : alphabet = "AaàBbCcDdEeéèFfGgH-
hIiJjKkLlMmNnOoPpQqRrSsTtUuùVvWwXxYyZz"
2. Écrire une fonction ordre_alphabetique(c1,c2) qui prend en argument deux carac-
tères alphabétiques et renvoie -1 si c1 est avant c2, 1 si c2 est avant c1 et 0 si c1 =
c2. On pourra utiliser la méthode index qui renvoie l’indice d’un élément dans une
chaîne de caractères.
3. Écrire une fonction ordre_lexicographique(m1,m2) qui prend en argument deux
mots et renvoie -1 si ”m1 < m2” pour l’ordre lexicographique, 0 si ”m1 = m2” et 1
si ”m1 > m2”. On utilisera la fonction ordre_alphabetique.
4. Écrire une fonction tri_lexicographique(liste) qui prend an argument une liste de
mots et renvoie la liste triée. On utilisera la fonction ordre_alphabetique etl’algo-
rithme du tri par insertion.
3. La démarche d’analyse descendante
3.1 Présentation
Dans ce chapitre, nous allons présenter la démarche d’analyse descendante. L’accent
est mis ici sur la démarche permettant de décomposer un problème qualifié difficile en
problèmes simples et élémentaires.
Découper un problème en sous problèmes nous impose de concevoir pour chaque
sous-problème un sous programme et de rassembler l’ensemble de sous-programmes
pour construire la solution finale. La notion de sous-programme ou de fonction est une
conséquence immédiate de la démarche d’analyse descendante.
Nous présenterons également la notion de fonction et quelques aspects techniques qui
lui sont associées et nous finirons, ce chapitre, par l’introduction de quelques fonctions
prédéfinies en python.
Voici un exemple de la vie quotidienne : faire des courses dans une grande surface
— Problème initial : faire des courses
— Sous-Problème 1 : "faire des courses" se décompose en :
1. Se préparer : écrire la liste des achats
46 Chapitre 3. La démarche d’analyse descendante
2. Sortir de la maison
3. Allez chez la boutique
4. faire effectivement des courses
5. revenir à la maison
6. ranger les achats dans leurs emplacement (La cuisine)
7. se laver les mains.
— Sous-problème 1.4 : faire effectivement des courses se décompose en :
1. rentrer dans la boutique
2. prendre un chariot
3. Parcourir la grande surface :Pour chaque article de votre liste d’achats, allez à
sa place et le poser dans le chariot
4. Passer à la caisse
5. Payer la somme
6. Sortir de la boutique.
— Sous problème 2.3 : se décompose en ...
Si l’on doit concevoir un logiciel qui permettrait à un robot d’assurer ces différentes tâches,
il y aurait sans doute des millions de lignes de code. Il serait donc judicieux de décomposer
le problème initial en sous problèmes simples bien raffinés afin de mener à bien ce projet.
Analyse du problème :
L’analyse du problème passe par l’identification des variables (données de programme)
d’entrées et de sorties d’une part et d’autre part par les traitements à effectuer :
3.2 La démarche d’analyse descendante 47
Les variables : Une lecture rapide du problème nous permettra d’identifier les objets
manipulés par le programme : — Une constante entière NB_MAX = 1000 contenant le
nombre maximal à saisir au clavier. — Une suite de valeurs : Pour cela, nous utiliserons
une liste pour y stocker ces valeurs.
Les traitements : Dans cette phase, nous allons décomposer le problème selon la
démarche d’analyse descendante :
1. Sous-problème 1 : saisir la suite de valeurs
2. Sous-problème 2 : mettre en ordre croissant cette suite
3. Sous-problème 3 : afficher la liste triée selon le format imposé.
(1)Saisir la suite de valeurs : On propose la méthode (algorithme) suivante :
1. Initialement, on crée une liste vide. Soit suite cette liste.
2. On répète la lecture au clavier d’un entier puis sa mémorisation dans la liste suite
exactement n fois avec n ≤ NB_MAX.
3. à la fin, on retourne cette liste.
1. Voir le chapitre 12
48 Chapitre 3. La démarche d’analyse descendante
Il reste maintenant à préciser comment trouver l’indice de l’élément minimal d’une liste
quelconque l. Le plus simple est de fixer que l’indice de minimum est initialement indice=0
puis parcourir la liste à partir de 1. À l’itération k, Si l[k] < l[0] alors dans ce cas on met à
jour la valeur de variable indice à k puisqu’on a trouvé un autre inférieur au minimum de
départ. d’où l’algorithme qui suit :
(3) Afficher la liste selon le format imposé Pour afficher une liste de n éléments à raison
de grid=10 par ligne (Format imposé 1 )on peut utiliser la méthode suivante :
Parcourir la liste dans l’ordre croissant des indices avec affichage de 10 premiers
éléments, puis afficher les 10 éléments qui suivent et ainsi de suite jusqu’à arriver à la fin
n
de la liste. On remarque que si n=200 et grid=10 alors il y a grid lignes à afficher puisque
n = 10 × 20 Ceci pourrait conduire à l’algorithme suivant :
3.2 La démarche d’analyse descendante 49
#Affichage de suite
grid=int(input("Entrer le nombre d’élément à afficher par ligne:"))
for k in range(n):
if (k % grid) == 0 and k!=0:
print()
print(f"{L[k]} ",end=’ ’)
print("\n--------------------------------")
print("Fin du problème")
fonctions principales :
La lecture de la suite
def s a i s i r ( n ) :
l = []
for k in range ( n ) :
x = i n t ( i n p u t ( f " E n t r e r l a v a l e u r numero { k } : " ) )
l . append ( x )
return l
d e f minimum ( l ) :
n = len ( l )
indice = 0
for i in range (1 , n ) :
if suite [ indice ]> suite [ i ] :
indice = i
return indice
def t r i S e l e c t ( l ) :
f o r i i n range ( n −1) :
i n d i c e = minimum ( l [ i : ] )
i f i n d i c e != i :
l [ i n d i c e ] , l [ i ]= l [ i ] , l [ i n d i c e ]
Solution du problème
NB_MAX = 1000
t e x t 1 = " E n t r e r l e nombre d ’ e l e m e n t a a f f i c h e r p a r l i g n e : "
t e x t 2 = " E n t r e r l e nombre t o t a l de v a l e u r s : "
n = int ( input ( text1 ) )
grid = int ( input ( text2 ) )
a s s e r t n <= NB_MAX
f :E →F
x 7−→ y
avec y = f (x) si possible ou une procédure (méthode de calcul)
La définition d’une fonction en python respecte la syntaxe suivante :
syntaxe générale d’une fonction python
def nom_fonction(Arguments):
"""
DocString
"""
global <variables globales>
<Bloc d’instructions>
return <valeur de la sortie>
Le nom de la fonction doit respecter les règles de nommage utilisées pour identifier
des variables :
— Il doit commencer par une lettre (y compris la lettre _ ),
— Il peut contenir des chiffre,
— Il ne doit pas contenir de l’espace ou d’opérateurs -, +, @, ...),
— Il ne doit pas être un mot clé réservé au langage if, for, while, ...
Si le nom est composé de plusieurs mots, utiliser la règle du dos de chameau (--̂-̂) : mot-
MotMot. La liste des arguments entre parenthèse peut avoir zéro ou plusieurs paramètres
séparés par virgule.
Notons ici que les arguments arg1, arg2, ... argn peuvent être des valeurs ou des
variables globales déclarées en dehors de son code. Les variables internes c’est-à-dire
celles déclarées à l’intérieure de la fonction ont une porté locales.
L’exemple qui suit montre que les variables a, b et c sont locales et les variables x, y, s
et d sont globales :
x = 3
y = 7
s = somme(x, y)
d = diff (x, y)
print(f"{x} + {y} = {s}"}
print(f"{x} - {y} = {d}"}
def f (a):
global c, d
c = c+1
d += a + c
f(3) # erreur
c = 1 # Ok
d = 0 # Ok
f (3) # c = 2 et d = 5
Mode de passage
Passage par valeur :
Dans un passage par valeur, les variables effectifs (celle passée à la fonction au moment
de son appel) sont copiés dans les paramètres formels. Les valeurs des arguments formels
restent inchangés après l’appel de la fonction. Les types non mutables (int, float, str,
complex, bool, tuple...) sont passés par valeur.
L’exemple qui suit montre que les variables a et b passées à la fonction echange reste
inchangées après son appel :
3.3 Les fonctions en Python (Approfondissement) 55
a = 10
b = 20
print (f"Avant echange: a={} et b={}".format(a, b))
echange(a, b)
print (f"Apres echange: a={} et b={}".format(a, b))
Les variables a et b à l’extérieur de la fonction echange sont copiées dans les variables
locales a et b et la fonction echange va permuter ses variables locales et non plus les
variables globales c’est pourquoi les variables a=10 et b= 20 reste inchangé après son
appel.
def a j o u t e r ( a , x ) :
a . append ( x )
a = [1 , 2 , 3]
p r i n t ( f " Avant l ’ a p p e l : a = { a } " )
a j o u t e r ( a , 5)
p r i n t ( f " Apres l ’ a p p e l : a = { a } " )
Python autorise d’appeler la fonction sans trop respecter l’ordre des arguments au
moment de la déclaration. Il suffit d’utiliser le nom du paramètre au moment de l’appel et
de préciser la valeur qu’il prend :
56 Chapitre 3. La démarche d’analyse descendante
def f1( ):
x=1
def f2( ) :
x=2
print("Au niveau de fonction f2, x=", x)
f2 ()
print( ”Au niveau de fonction f1, x=", x)
f1 ()
Si on introduit le mot global dans la fonction fille alors les variables locales concernées
de la fonction mère seront modifiées :
def f1( ):
x=1
def f2( ) :
global x
x=2
print("Au niveau de fonction f2, x=", x)
f2 ()
print( ”Au niveau de fonction f1, x=", x)
f1 ()
On peut passer le nom d’une fonction (sa référence) comme argument d’une autre
fonction. L’exemple qui suit montre l’usage d’un tel passage de fonction :
3.3 Les fonctions en Python (Approfondissement) 57
def f ( x ) :
r e t u r n x*x
d e f d f ( f , x0 ) :
h = 0.000000000001
r e t u r n ( f ( x0+h ) − f ( x0 ) ) / h
On peut assigner une fonction à une variable comme tout autre objet python
— X=f
— X(5)
On peut également placer les fonctions dans des listes, tuples ou dictionnaires :
— d={’a’ : f, ‘b’ : g}
— d[’a’](5)
0! = 1 , si n = 0
n! = 1 × 2 × ... × n , si n > 0
version itérative
def f a c t o r i e l l e ( n ) :
a s s e r t n >= 0
f = 1
f o r k i n range ( 2 , n +1) :
f *= k
return f
0! = 1 , si n = 0
n! = (n − 1)! × n , si n > 0
58 Chapitre 3. La démarche d’analyse descendante
version récursive
def f a c t o r i e l l e ( n ) :
a s s e r t n >= 0
i f n == 0 : r e t u r n 1
r e t u r n n * f a c t o r i e l l e ( n −1)
Cela définit une fonction anonyme qui contient un simple renvoi. Par exemple, la
fonction f : x 7−→ f (x) = x(x − 1) peut être déclarer comme suit :
Exemple
lambda x : x*(x-1)
fonction map()
Pour mapper une fonction avec un itérateur, on utilise la fonction prédéfinie map().
C’est une fonction à deux paramètres ; Le premier sert à définir une expression et le
deuxième est un itérateur. Par exemple map(f, liste) permet de retourner un itérateur de
type map qu’on peut le convertir à une liste (via list) :
fonction filter()
syntaxe de filter()
filter(fonction, sequence)
La fonction filtrer permet de filtrer tous les éléments d’une séquence pour lequel la
fonction retourne True. Autrement dit :
— La fonction filter(f, L) a besoin d’une fonction f comme premier argument.
— f doit retourner une valeur booléenne, soit Vrai ou Faux.
— Cette fonction sera appliquée à tous les éléments de la liste L.
3.4 Exercices 59
— Seulement les éléments où la fonction f retourne Vrai seront produites par l’itérateur,
qui est la valeur de retour de filtre (fonction, séquence).
Par exemple, filter(lambda x : x%3, range(20)) renvoie la liste :
La fonction zip() retourne un itérateur de tuples de type zip qu’on peut le convertir en
liste, dictionnaire, tuple ou un set :
— Si on passe zéro arguments, zip() retourne un itérateur vide ;
— Si on passe un seul itérateur, zip() retourne un itérateur de tuples où chaque tuple
contient uniquement un seul élément ;
— Si on passe plusieurs itérateur, zip() retourne un itérateur de tuples où chaque tuple
contient des éléments de tous les itérateurs
— Supposons qu’on a passé deux itérateurs à la fonction zip() où le premier contient
trois éléments et le seconde contient cinq éléments. Alors, zip() retourne un itérateur
contenant uniquement trois tuples car zip va s’arrêter quand l’itérateur de taille
minimale pointe vers sa fin.
3.4 Exercices
Exercise 3.1 On veut réunir dans un programme python "ma_bibliothque.py" un certain
nombre des outils mathématiques bien connus pour faciliter l’utilisation. Pour cela, on
définit d’abord pour chaque outils une fonction qui réalise la tâche de l’outil. Ensuite,
on définit un menu qui permet l’accès aux outils. Selon le choix d’outils, on propose les
saisies de données adéquates et exécute la fonction correspondante et affiche le résultat.
Écrire ce programme et proposer pour cet exercice les fonctions suivantes :
1. valeurabsolue(x) : retourne la valeur absolue d’un nombre réel x
60 Chapitre 3. La démarche d’analyse descendante
2. puissance(x, n) : calcule xn , n peut être 0, < 0 ou > 0.
3. factorielle(n) : calcule n! (factoriel de n = 1 ∗ 2 ∗ ... ∗ (n − 1) ∗ n , n ≥ 0)
4. estpair(n) : retourne True si n est pair, False sinon
5. estimpair(n) : retourne True si n est impair, False sinon
6. diviseurs(n) :affiche les diviseurs de n
7. nombrediviseurs(n) : retourne le nombre de diviseurs de n
8. estpremier(n) : retourne True si n est premier, False sinon.
9. pgcd(a, b) : retourne le plus grand diviseur commun de a et de b.
10. premiers2(a, b) : retourne True si a et b sont premiers entre eux, False sinon
11. ppcm(a,b) : retourne le plus petit commun multiple de a et b
12. racinecarrée(x, eps) : retourne la racine carrée d’un réel positif x avec la précision
eps selon l’algorithme suivante : à partir d’un nombre aléatoire y0 , calculer
y1 = 12 (y0 + yx0 ) :
— Si |y1 − y0 | ≥ 0 alors recalculer y1 en fixant que y0 = y1 ,
— Sinon, arrêter les calcules
la valeur absolue de x est la dernière valeur de y1 calculée. (ceci permet de
programmer la limite de la suite (Un ) (limUn ) où (Un+1 = 12 (Un + Uxn ))
13. équation1(a,b) retourne la solution de l’équation de premier degré ax + b = 0
14. équation2(a,b,c) retourne la solution de l’équation de deuxième degré ax2 + bx +
c=0
■
Exercise 3.2 Nous considérons dans tout l’exercice des listes d’entiers de taille 20 avec
des doublons.
Première partie :
Deuxième partie :
Nous considérons les deux listes l_pair et l_impair remplies précédemment. Écrivez
un programme Python qui :
1. calcule et affiche le plus grand entier pair de la liste l_pair.
2. calcule et affiche le plus grand entier impair de la liste l_impair.
3. calcule et affiche le plus grand des entiers pairs et impairs. L’exécution de
votre programme devra donner un affichage sur écran semblable à l’exemple
ci-dessous :
Le plus grand des entiers pairs est : 22
Le plus grand des entiers impairs est : 35
Le plus grand des entiers pairs et impairs est : 35
Troisième partie :
Nous considérons les mêmes listes précédentes l_pair et l_impair. Écrivez un pro-
gramme Python qui :
62 Chapitre 3. La démarche d’analyse descendante
1. calcule pour chaque entier de l_pair son nombre d’entiers appartenant à la liste
l_impair strictement supérieurs. On évitera les affichages redondants. L’exécution
de votre programme devra donner un affichage sur écran semblable à l’exemple
ci-dessous :
3 entiers impairs sont strictement supérieurs à 2 ;
4 entiers impairs sont strictement supérieurs à 4 ;
2 entiers impairs sont strictement supérieurs à 16 ;
...
NB : il est formellement interdit d’utiliser les fonctions prédéfinies sur les listes telles
que max(l), print(l), etc. où l est une liste quelconque. ■
Exercise 3.3 On désire écrire un programme qui calcule et affiche les résultats obtenues
par les N étudiants qui se sont présentés à un concours.
Il y a 8 matières au programme du concours (français, informatique, math, etc.), et,
pour le concours, les étudiants passent une épreuve par matière.
Chaque épreuve est notée sur 20 et pondérée par un coefficient (par exemple : le
français a pour coefficient 3 et l’informatique a pour coefficient 5). Pour chaque étudiant,
le calcul de la moyenne qu’il a obtenue au concours se fera donc à partir de ses notes et
des coefficients qui pondèrent les matières.
Les étudiants sont numérotés de 0 à N-1. Les matières sont numérotées de 0 à 7.
Les coefficients des 8 matières sont enregistrés dans la variable coeff, qui est une
liste de 8 entiers tel que coeff[i] est le coefficient de la matière i.
Les notes obtenues par les étudiants sont enregistrées dans la liste list_notes, liste
de réels de dimensions 2 et de taille N × 8, tel que la variable list_notes[e][i] contient la
note obtenue par l’étudiant numéro e à la matière numéro i.
Par ailleurs, on utilisera aussi (voir la question 6) dans le programme tab_moyennes,
de type liste de réels de taille N, dans lequel on enregistrera les moyennes des étudiants :
la variable tab_moyennes[e] contiendra la moyenne que l’étudiant numéro e a obtenue
au concours.
les trois listes coeff, list_notes et tab_moyennes seront des variables globales du
programme.
Première partie
Le but de cette partie est d’écrire quelques fonctions qui seront utilisées dans la
deuxième partie. Il est formellement interdit d’utiliser les fonctions prédéfinies sur les
listes telles que max(l), print(l), etc. où l est une liste quelconque.
Question 1 :
Écrire la fonction somme_list(l) qui calcule et renvoie la somme des éléments d’une
liste l de nombres.
3.4 Exercices 63
Question 2 :
Question 3 :
Soit x une variable float, qui contient une note comprise entre 0 et 20. On désire
écrire une fonction max_list(l) qui calcule et renvoie la valeur de x arrondie au demi-
point supérieur.
On rappelle que l’instruction y = int(x) affecte à y la valeur entière de x.
Le calcule de la valeur de x arrondie au demi-point supérieur se fait de la façons
suivante :
— si x est égale à int(x), la valeur arrondie est x ;
— si x- int(x) est inférieur ou égale à 0.5, la valeur arrondie est int(x)+0.5 ;
— si x- int(x) est supérieur ou égale à 0.5, la valeur arrondie est int(x)+1 ;
Écrire la fonction arrondie (x) qui calcule et renvoie la valeur arrondie de x
Deuxième partie
Question 4 :
Question 5 :
Écrire la fonction meilleur_note(m) qui calcule et renvoie la meilleur note qui a été
obtenue dans la matière m par l’ensemble des étudiants.
Question 6 :
On désire calculer les moyennes que les étudiants ont obtenues au concours, les
arrondir au demi-point supérieur, puis les enregistrer dans la liste tab_moyennes.
Pour cela, écrire la fonction calculer_moyenne() qui :
1. calcule la somme des coefficients (utilisez la fonction somme_list(l) de la première
partie)
2. pour chaque étudiant :
— calculer la somme de ses notes pondérées par les coefficients ;
— calcule sa moyenne ;
— arrondit cette moyenne au demi-point supérieur ;
— enregistre dans la liste tab_moyennes cette valeur arrondie de la moyenne,
Question 7 :
A partir des données contenues dans la liste tab_moyennes ; on désire afficher les
moyennes obtenues au concours, sous la forme suivante, avec une précision d’une
64 Chapitre 3. La démarche d’analyse descendante
décimale pour la moyenne :
Ecrire la fonction afficher_moyenne qui affiche la liste des moyennes selon le format
ci-dessus.
Question 8 :
On suppose que l’on dispose d’une fonction saisir_note() qui permet de remplir la
liste list_notes.
Ecrire la fonction main() qui, en appelant les fonctions précédentes, permet de :
— saisir les notes,
— pour chaque matière, affiche à l’écran la meilleur note qui a été obtenue dans
cette matière,
— calculer toutes les moyennes et les afficher.
Question 9 :
On désire maintenant faire à l’écran un affichage des résultats par ordre de mérite,
sous la forme suivante :
Dans ce chapitre, nous étudions deux structures des données : Les piles et les files.
Ces deux structures jouent un rôle très important non seulement dans la conception
et la programmation des applications modernes mais aussi en informatique elle même,
notamment dans la gestion de mémoire, la programmation de compilateur pour la correction
syntaxique de code source et dans l’exécution des fonctions récursives, etc.
Le but, donc, de ce chapitre est de décrire les représentations des structures de données
telles : les piles et les files. L’autre but recherché est de voir l’importance de ces structures
à travers quelques exemples d’applications.
4.1 Pile
[9] Quand on parle d’une structure de données on parle d’une organisation logique des
données permettant de simplifier ou d’accélérer leur traitement.
Definition 4.1.1 — pile. Une pile est une structure de données qui suit le principe
dernier entré est le premier à servir (Ou LIFO pour Last In - First Out ).
C est empilé sur B, lui-même empilé sur A. On peut soit retirer C de la pile (on dit qu’on «
66 Chapitre 4. Pile et File
dépile » C), soit ajouter un quatrième élément D (on dit qu’on « empile » D). Si on veut
accéder à l’élément A, il faut commencer par dépiler C, puis B.
Cette structure est utile quand-t-on veut stocker (archiver) des éléments (programmes,
fichiers, processus, données simple (int, float, str, bool, ...), etc.) dans un ordre bien précis
de telle façon à cacher ses éléments sauf l’élément qui est au sommet. Le seul élément
qu’on peut extraire de la liste et celui qui se trouvent au sommet. dans le cas où on veut
extraire les autres, il suffit, donc, les parcourir en utilisant une boucle for ou while.
L’exemple traditionnel de l’utilisation d’une pile est celui d’un navigateur web. Une
pile sert à mémoriser les pages Web visitées. L’adresse de chaque nouvelle page visitée
est empilée et l’utilisateur dépile l’adresse de la page précédente en cliquant le bouton "
Afficher la page précédente".
Le deuxième exemple est la mémorisation des caractères(ou les actions) tapés par
l’utilisateur dans un Texteur (Microsoft word, gedit, Bloc Note, ...). La fonction "Annuler la
frappe" (en anglais "Undo" ou ctrl+z) d’un traitement de texte mémorise les modifications
apportées au texte dans une pile. Et à chaque fois que vous annuler une opération, le
logiciel dépile le sommet.
Le troisième exemple est la pile de vérification de la correction des parenthèses d’une
chaîne de caractères. Nous traitons cet exemple une fois on a implémenté la structure pile
en python.
création de la pile
À la création, la pile contient 0 élément (p[0]=0). Après les opérations d’ajout et de retrait,
cette capacité va être incrémenter ou décrémenter de telle façon de ne pas dépasser sa
capacité maximale c puisqu’on parle d’une pile à capacité finie.
Une fois fait, on ne peut pas appliquer les méthodes classiques agissant sur les listes
telles que : append et pop car elles modifient la structure(la taille qu’on a appelée capacité
c ) de notre liste. La seule opération autorisée est len(p) qui renvoie la capacité c maximale
de notre pile. p[0] va servir de la taille réelle de notre pile (nombre d’éléments insérés).
Empiler un élément :
La deuxième opération à définir, une fois la pile est crée, est la fonction qui permet
d’empiler un élément e dans une pile p :
def empiler (p , e ) :
n = p [0]
a s s e r t n < l e n ( p ) −1
n +=1
p [0] = n
p[n] = e
Fonction empiler
Avant d’empiler, il faut extraire l’information qui indique sa taille réelle n. Si la taille n est
strictement inférieur à sa capacité maximale c= len(p) et qu’il reste au moins une place
pour l’élément e (< len(p) -1) alors dans ce cas on peut empiler e au sommet n+1 car le
dernier élément avant d’empiler e se trouve à l’indice n. Dans le cas où la pile est pleine
(le sommet se trouve à l’indice len(p)-1) on ne peut pas ajouter des éléments afin de ne pas
avoir le problème de débordement(dépassement de capacité ou overflow en anglais).
Dépiler un élément :
La troisième opération à définir est celle qui permet de dépiler un élément d’une pile p.
Le seul élément qu’on peut dépiler est celui au sommet (loi LIFO :last in first out) :
def d e p i l e r ( p ) :
n = p [0]
68 Chapitre 4. Pile et File
a s s e r t n >0
p [ 0 ] = n −1
return p [0]
Nous commençons le traitement par l’instruction qui nous indique la capacité réelle de la
pile(n = p[0]). Il faut ensuite s’assurer que la pile n’est pas vide sinon rien à dépiler (assert
n>0). Enfin,et avant de renvoyer l’élément à dépiler, il faut mettre à jour la taille réelle de
la pile p (p[0] = n-1).
Cependant, pour ne pas avoir une erreur d’assertion, on peut afficher le message ’under
low’ si la pile est vide.
def d e p i l e r ( p ) :
n = p [0]
i f n ==0:
p r i n t ( " E r r e u r : underFlow " )
else :
data= p[n]
p [ n ] = None
n=n −1
p [0] = n
return data
Autre opérations
def taille_max ( p ) :
return len (p)
def t a i l l e _ r e e l l e ( p ) :
return p [0]
def est_vide ( p ) :
r e t u r n t a i l l e _ r e e l l e ( p ) ==0
def e s t _ p l e i n e ( p ) :
r e t u r n t a i l l e _ r e e l l e ( p ) == t a i l l e _ m a x ( p )
def cr é e r _ p i l e ( ) :
return []
Empiler
def empiler (p , e ) :
p . append ( e )
Dépiler
def d e p i l e r ( p ) :
a s s e r t l e n ( p ) >0
r e t u r n p . pop ( )
Autre fonctions
fonction prédicat pour tester si la pile est vide
def est_vide ( p ) :
r e t u r n l e n ( p ) == 0
Le code Python qui suit permet de vérifier si un mot est bien parenthésé ou non :
def bienParenthese ( s ) :
p = creer_pile ()
for i in range ( len ( s ) ) :
i f s [ i ]== ’ ( ’ :
empiler (p , s [ i ])
e l i f s [ i ]== ’ ) ’ :
if est_vide (p) :
return False
depiler (p)
else :
continue
return est_vide (p)
4.2 Files
4.2.1 Notion de File
Definition 4.2.1 — File. Une file[9] est une structure de données dynamique dans
laquelle on insère des nouveaux éléments à la fin (queue) et où on enlève des éléments
au début (tête de file). La file est basée sur le principe "Premier entré est le premier à
servir", on parle de mode d’accès FIFO (First In, First Out), par opposition au mode
d’accès LIFO (Last In First Out ) des piles.
Le fonctionnement ressemble à une file d’attente : les premières personnes à arriver sont
les premières personnes à sortir de la file. Une file est modifiée à ses deux bouts :
def E n f i l e r ( f , e ) :
f . append ( e )
def D e f i l e r ( f ) :
a s s e r t l e n ( f ) >0
r e t u r n f . pop ( 0 )
def EstVide ( f ) :
r e t u r n f ==[]
def Tete ( f ) :
72 Chapitre 4. Pile et File
return f [0]
d e f Queue ( f ) : s
r e t u r n f [ l e n ( f ) −1]
4.3 Exercices
Exercise 4.2 Écrire une fonction copier_pile(p) qui prend en argument une pile p et
retourne une copie de p sans modifier p. ■
Exercise 4.3 Écrire une fonction inverser_pile(p) qui prend en argument une pile p et
retourne une autre pile dont les éléments sont les éléments de p dans l’ordre inverse, p
n’est pas modifiée. ■
Exercise 4.4 On dispose d’une structure de pile à laquelle sont associées les seules
opérations ou fonctions de base : creer_pile(p), empiler(p), sommet(p), depiler(p),
est_vide(p).
Le but est de construire les opérations suivantes à l’aide de ces éléments :
1. Une fonction depilerK(p,k) qui dépile k éléments si la pile p en contient au moins
k et dépile toute la pile sinon sans lever d’erreur.
2. Une fonction depilerJusqu(p,e) qui dépile p tant que l’élément e n’est pas rencon-
tré ou p n’est pas vide.
3. Une fonction perm2(p) qui permute dans p, le sommet et le terme suivant.
4. Une fonction rot(p,k) qui réalise une permutation circulaire sur les k éléments
premiers éléments de la pile.
■
Exercise 4.5 La notation polonaise inversée est une façon d’écrire les expressions
arithmétiques sans indiquer de multiples parenthèses. Une expression arithmétique
écrite en notation polonaise inversée est une suite de nombres et d’opérateurs (+, -, / ou
*) et se lit (et s’évalue) de gauche à droite de la façon suivante :
— lorsqu’un nombre est lu, il est empilé sur une pile (initialement vide)
— lorsqu’un opérateur est lu, les deux premiers éléments de la pile sont récupérés et
dépilés, l’opération est effectuée sur les deux valeurs obtenues, et le résultat est
empilé ;
— le résultat de l’expression est le premier (et normalement le seul) élément de la
pile à la fin de la lecture.
Notre objectif est d’implémenter cette méthode en un programme python :
1. Appliquer la méthode exposée pour calculer : 17 10 - , 3 28 7 / + et 3 28 + 7 /
Comment s’écrivent ces expressions en notation classique ?
2. Traduire en notation polonaise inversée les expressions suivantes : (19 * 6) - 7 et
(4 - 2 * (7 + 6)) + 3 * 5
4.3 Exercices 73
3. Écrire une fonction qui évalue une expression polonaise inversée, composée
d’entiers entre 0 et 9 et des quatre opérations élémentaires. On pourra par exemple
suivre les étapes suivantes :
— une fonction qui prend en entrée un caractère et renvoie vrai s’il s’agit d’une
opération élémentaire et faux sinon,
— une fonction qui prend un symbole-opération et deux entiers et qui renvoie
le résultat de l’opération,
— enfin, la fonction d’évaluation.
4. testez la fonction pour calculer : 17 10 - , 3 28 7 / + et 3 28 + 7 /
■
II
Les structures de données
non linéaires
5 Dict et Set . . . . . . . . . . . . . . . . . . . . . . . . . 77
5.1 Présentation
5.2 Fonction de hachage
5.3 Les tableaux associatifs : dict
5.4 Les ensembles : set
5.5 Pile implémenté par un dictionnaire
5.6 Conclusion
5.7 Exercices
5. Dict et Set
5.1 Présentation
Dans ce chapitre, nous présenterons deux structures de données non linéaires : les
dictionnaires et les ensembles. Nous présenterons également le concept de base derrière
ces deux structures : fonctions de hachage.
∀x ̸= y ⇒ f (x) ̸= f (y)
Dans ce cas (f est injective), on dit que la fonction est sans collision. Il est important
de choisir une fonction de hachage sécurisée, car il existe des attaques pour trouver des
collisions, ce qui peut compromettre la sécurité de vos données.
Les fonctions de hachage sont utilisées dans de nombreux domaines, tels que la sécurité
informatique (par exemple, pour stocker des mots de passe sécurisés), la compression
de données (par exemple, pour trouver rapidement des doublons dans les données) et les
structures de données telles que les tables de hachage (où les entrées sont stockées en
fonction de leur hash). Les fonctions de hachage couramment utilisées sont : SHA-256,
SHA-512 et MD5.
78 Chapitre 5. Dict et Set
Les tables de hachage sont souvent utilisées pour implémenter des dictionnaires ou des
ensembles en informatique, car elles permettent un accès rapide aux entrées en utilisant
leur clé. Les tables de hachage sont particulièrement utiles pour les opérations d’insertion,
de suppression et de recherche, car elles peuvent être effectuées en temps constant en
moyenne (par opposition à un temps de recherche linéaire pour les listes simples).
Ainsi, on réserve un tableau de taille fixe et on stocke les données dans une case
correspondant à son hash. Pour insérer le contact (’ali’, ’+212610040608’, on calcule le
hash de la clé =’ali’ (f(’ali’)=2) et on stocke le couple (’ali’, ’+212610040608’) dans la
case d’index 2(figure 1).
Cependant, les tables de hachage peuvent également être sujettes à des collisions, où
plusieurs entrées différentes produisent le même hash. Pour éviter les collisions, il est
important de choisir une fonction de hachage efficace qui distribue uniformément les
entrées dans les différentes cases de la table.
Les fonctions de hachage sans collision sont utilisées pour assigner un code numérique
unique à chaque élément d’une structure de données, telle qu’un dictionnaire. Voici
quelques exemples de fonctions de hachage simples :
1. Fonction de hachage de somme : elle consiste à additionner les codes ASCII de
chaque caractère d’une chaîne de caractères pour obtenir un code de hachage unique.
Par exemple, pour la chaîne ’hello’, la fonction de hachage serait 104 + 101 + 108 +
108 + 111 = 532.
5.3 Les tableaux associatifs : dict 79
Les dictionnaires sont des structures de données qui permettent de stocker des paires
clé-valeur. Les clés sont uniques dans un dictionnaire et permettent de retrouver la valeur
associée.
>>> # ou encore
>>> dict_1.get(chien)
dog
Les clés, dans un dictionnaire sont uniques et peuvent être définies par des objets
immuables (str, int, float, tuple, ...). les listes sont mutables et, donc, ne peuvent pas être
utilisées comme des clés. La raison est très simple : au moment de la création d’un couple
(liste :valeur) on calcule le hash de cet objet liste et on le stocke dans sa case mais si on
5.3 Les tableaux associatifs : dict 81
modifie cet objet on risque de trouver un autre hash et on perd l’association list :valeur.
Ainsi, Python génère une erreur de type unhashable type
Les dictionnaires sont des objets modifiables dans le sens où on peut modifier la valeur
d’une clé. Toute modification d’une valeur associée à une clé qui n’existe pas impliquera
sa création. On peut également supprimer des clés :
Les dictionnaire sont itérables : on peut parcourir les données d’un dictionnaire via la
liste de ses clés (par défaut) :
chat:= cat
chien:= dog
oiseau:= bird
cow:= vache
les clés (keys) dans contacts sont les noms des personnes et les valeurs sont les
informations associées à ces personnes. On se limite aux informations suivantes : last_name,
birthday, birthplace, email et phonenumber. Ces informations vont être stockées dans un
autres dictionnaire values. Par exemple, le contact ’ElIbrahimi’ aura la forme suivante :
contacts = {
’ElIbrahimi’:
{
’last_name’ : ’Ali’ ,
’birthday’ : ’2001-12-25’ ,
’birthplace’: ’Beni Mellal’ ,
’email’ : ’ali.ibrahimi@abc.net’,
’phonenumber: ’+212610579864’
}
}
notre objectif, dans ce mini-projet, est de pouvoir gérer les contactes, c’est à dire
ajouter, modifier, supprimer et rechercher un contact. Nous commençons, donc, par la
définition et la création de ces primitives(fonctions) :
84 Chapitre 5. Dict et Set
def remove(key):
if key in contacts:
del contacts[key]
print("a contact has been removed successfuly")
else:
print(contact,key, "not found")
def find(name):
found = []
for key in contacts:
if name in key:
found.append(key)
return found
def get_one(name):
return contacts[name] if name in contacts else "not found"
La couche de présentation :
une fois les primitives sont définies, on définit les fonctions nécessaires au bon fonc-
tionnement de notre application, notamment les fonctions qui permettent l’affichage des
informations d’un contact. à savoir :
— une fonction print_info() qui affiche une information se forme d’une case d’une table
en mode texte ;
— une fonction print_one_contact() qui affiche un contact se forme d’une ligne d’une
table table en mode texte ;
—
— une fonction print_all_contact() qui affiche les contacts se forme d’une table en
mode texte ;
5.3 Les tableaux associatifs : dict 85
def print_value(value):
print(f"| {value:14}",end=’ ’)
def new_line():
return "+"+’-’*107+’+\n’
def print_headers():
headers = f"| {’First name’:14} | {’Last name’:14} |
headers += f" {’Birthday’:14} | {’birthplace’:14} |"
headers += f" {’Phone number’:14} | {’Adress email’:20} |\n"
print(new_line())
print(headers)
print(new_line())
def print_contact(name):
info = contacts[name]
print_value(name)
for value in info.values():
print_value(value)
print(’|’)
def print_all_contacts():
print_headers()
for contact in contacts:
print_contact(contact)
print(new_line())
print()
def get_value(attribute,n=14):
return input(f"\t\tSet a new value of {attribute:{n}}:> ")
def create_contact():
values = {}
first_name = get_value("first_name")
values[’last_name’] = get_value("last_name")
values[’birthday ’] = get_value("birthday")
values[’birthplace’] = get_value("birthplace")
values[’phonenumber’] = get_value("phonenumber")
values[’email’] = get_value("email",n=20)
add(first_name,values)
def update_contact_by_name():
name = get_value("first name")
for contact in find(name):
print_contact(contact)
query=input("\tDo you want to modify this contact[Y|N]?:>")
if query.lower()==’y’:
values = contacts[contact]
for attribute, value in values.items():
response=input(f"\tUpdate {attribute}’value[y|n]?:>")
if response.lower()==’y’:
new_value = get_value(attribute)
set_value(values, attribute, new_value)
update(contact, values)
def find_contact_by_name():
name = input("get the first name:> ")
print_headers()
for contact in find(name):
print_contact(contact)
print()
def remove_contact_by_name():
name = input("get the first name:> ")
for contact in find(name):
print_contact(contact)
query = input("Do yo want to delete this contact[y,n]?:>")
if query.lower==’y’:
remove(contact)
88 Chapitre 5. Dict et Set
def main():
menu ="""
1 - add contact(s)
2 - find contact(s)
3 - remove contact(s)
4 - update contact(s)
5 - display contact(s)
6 - quit
"""
actions = {1:create_contact, 2:find_contact_by_name ,
3:remove_contact_by_name, 4:update_contact_by_name,
5:print_all_contacts , 6:exit
}
while True:
print(menu)
resp = int(input("Your choice:> "))
if resp in range(1,6):
function=actions.get(resp)
function()
elif resp == 6:
print ("bye")
break
else:
print("Error!!: get an integer fro 1 to 6")
continue
Voici la trace d’un test de la fonction main() pour montrer un déroulement de l’exécu-
tion :
1 - add contact(s)
2 - find contact(s)
3 - remove contact(s)
4 - update contact(s)
5 - display contact(s)
6 - quit
Your choice:> 1
Set a new value of first_name :> adoch
Set a new value of last_name :> mohammedo
Set a new value of birthday :> 2002-05-18
Set a new value of birthplace :> Rabta
5.3 Les tableaux associatifs : dict 89
1 - add contact(s)
2 - find contact(s)
3 - remove contact(s)
4 - update contact(s)
5 - display contact(s)
6 - quit
Your choice:> 1
Set a new value of first_name :> Imami
Set a new value of last_name :> Nora
Set a new value of birthday :> 1998-12-25
Set a new value of birthplace :> Fès
Set a new value of phonenumber :> +212661587968
Set a new value of email :> n.imami@abc.net
a contact has been added successfuly
1 - add contact(s)
2 - find contact(s)
3 - remove contact(s)
4 - update contact(s)
5 - display contact(s)
6 - quit
Your choice:> 1
Set a new value of first_name :> Kadouri
Set a new value of last_name :> rachid
Set a new value of birthday :> 2000-12-13
Set a new value of birthplace :> Agadir
Set a new value of phonenumber :> +212569854732
Set a new value of email :> r.kadouri@site.org
a contact has been added successfuly
1 - add contact(s)
2 - find contact(s)
3 - remove contact(s)
4 - update contact(s)
5 - display contact(s)
6 - quit
Your choice:> 5
+-----------------------------------------------------------------------------------
90 Chapitre 5. Dict et Set
| First name | Last name | Birthday | birthplace | Phone number | Adress email
+-----------------------------------------------------------------------------------
1 - add contact(s)
2 - find contact(s)
3 - remove contact(s)
4 - update contact(s)
5 - display contact(s)
6 - quit
Your choice:> 4
Set a new value of first name :> adoc
| adoch | mohammedo | 2002-05-18 | Rabta | +212756895213 | med.adoch@xyz.
Do you want to modify this contact [Y|N]? :> y
Updating last_name’value,[Y|N]? :> y
Set a new value of last_name :> mohamed
Updating birthday ’value,[Y|N]? :> n
Updating birthplace’value,[Y|N]? :> y
Set a new value of birthplace :> Rabat
Updating phonenumber’value,[Y|N]? :> n
Updating email’value,[Y|N]? :> n
a contact has been updated successfuly
1 - add contact(s)
2 - find contact(s)
3 - remove contact(s)
4 - update contact(s)
5 - display contact(s)
6 - quit
Your choice:> 5
+-----------------------------------------------------------------------------------
| First name | Last name | Birthday | birthplace | Phone number | Adress email
5.3 Les tableaux associatifs : dict 91
+-----------------------------------------------------------------------------------
1 - add contact(s)
2 - find contact(s)
3 - remove contact(s)
4 - update contact(s)
5 - display contact(s)
6 - quit
Your choice:> 3
get the first name:> Imam
| Imami | Nora | 1998-12-25 | Fès | +212661587968 | n.imami@abc.net
Do yo want to delete this contact[y,n]? :> y
1 - add contact(s)
2 - find contact(s)
3 - remove contact(s)
4 - update contact(s)
5 - display contact(s)
6 - quit
Your choice:> 8
Error!!: get an integer fro 1 to 6
1 - add contact(s)
2 - find contact(s)
3 - remove contact(s)
4 - update contact(s)
5 - display contact(s)
6 - quit
Your choice:> 6
bye
92 Chapitre 5. Dict et Set
On peut créer un ensemble via les accolades comme les dictionnaire mais sans clés :
un ensemble de valeurs uniqueq :
Création
>>> # première méthode
>>> set_1 = set([1, 2, 3, 4, 4, 4])
>>> set_1 # pas d’occurrence multiple
{1, 2, 3, 4}
>>> ’c’ in E
True
>>> ’x’ in E
False
Les set sont itérables : on peut parcourir les éléments d’un set :
5.4 Les ensembles : set 93
Test d’appartenance
>>> for e in E:print(e)
’a’
’b’
’c’
’d’
On peut ajouter ou supprimer un élément au set grâce aux méthodes add, discard,
remove :
L’ajout et la suppression
>>> E.add(’x’)
>>> E
{’a’, ’b’, ’c’, ’d’, ’x’}
On peut faire les opérations ensembliste telles que l’union, l’intersection, la différence
et la différence symétrique
94 Chapitre 5. Dict et Set
Opérations ensemblistes
>>> A = {’a’, ’b’, ’c’, ’d’}
>>> B = {’g’, ’c’, ’d’, ’f’}
Les set sont, comme les dict, non ordonnée c’est à dire que les éléments ne sont pas
ajoutés dans l’ordre de leurs apparitions. Dans l’exemple précédent, L’élément supprimé
est ’c’ et non plus le dernier élément ajouté ’d’
Vous pouvez implémenter une pile en utilisant un dictionnaire où les clés représentent
l’ordre d’ajout des éléments et les valeurs représentent les éléments eux-mêmes. Chaque
fois que vous ajoutez un élément à la pile, vous pouvez donner à sa clé un nouveau numéro
5.6 Conclusion 95
unique. Lorsque vous retirez un élément de la pile, vous pouvez retirer l’élément associé à
la clé la plus élevée.
Voici un exemple d’implémentation d’une pile à l’aide d’un dictionnaire en Python :
stack = {}
index = 0
def push(element):
global index
stack[index] = element
index += 1
def pop():
global index
if index == 0:
return None
index -= 1
element = stack[index]
del stack[index]
return element
Notez que cette implémentation utilise une variable globale index pour suivre l’ordre
d’ajout des éléments à la pile. Cela permet d’assigner une nouvelle clé unique à chaque
élément ajouté à la pile.
vous ne pouvez pas implémenter une pile en utilisant des ensembles (sets) en Python.
Les ensembles sont des structures de données non ordonnées qui ne conservent pas l’ordre
d’insertion des éléments. Par conséquent, ils ne peuvent pas être utilisés pour implémenter
une pile, qui nécessite de connaître l’ordre d’ajout des éléments.
Cependant, vous pouvez utiliser des ensembles pour stocker des éléments uniques et
effectuer des opérations telles que l’union, l’intersection et la différence sur les ensembles.
Les ensembles sont souvent utilisés pour supprimer les doublons dans des collections de
données ou pour effectuer des tests de présence rapides.
5.6 Conclusion
Les dictionnaires et les ensembles présentent plusieurs avantages par rapport à d’autres
structures de données en Python, tels que les liste :
— Temps d’accès rapide : les dictionnaires et les ensembles utilisent une structure de
données appelée table de hachage qui permet d’accéder rapidement à un élément en
fonction de sa clé ou de sa valeur.
— Stockage d’éléments uniques : les ensembles ne peuvent stocker que des éléments
uniques, ce qui peut être très utile lorsque vous avez besoin de vérifier l’existence
d’un élément sans duplicata.
— Modification facile : les dictionnaires peuvent être modifiés en ajoutant, en suppri-
mant ou en modifiant des paires clé-valeur, ce qui peut être très utile lorsque vous
avez besoin de stocker des informations qui peuvent changer au fil du temps.
96 Chapitre 5. Dict et Set
— Taille dynamique : les dictionnaires et les ensembles peuvent être agrandis ou réduits
en fonction des besoins, ce qui les rend plus flexibles que les listes qui ont une taille
fixe une fois définies.
— Utilisation pour des tâches spécifiques : les dictionnaires sont souvent utilisés pour
stocker des données structurées, tandis que les ensembles sont souvent utilisés pour
des tâches telles que la vérification de l’existence d’un élément ou la suppression
des duplicatas.
5.7 Exercices
Exercise 5.1 Implémenter en Python, les fonctions suivantes dont chaque fonction est
décrite par son entrée et sa sortie :
1. Grouper les éléments d’une liste en fonction d’une clé :
— Entrée : Une liste de tuples lst et une fonction de clé key_func ;
— Sortie : Un dictionnaire qui groupe les éléments de la liste en fonction de la
valeur renvoyée par key_func pour chaque élément.
2. Union de deux dictionnaires : :
— Entrée : Deux dictionnaires d1 et d2 ;
— Sortie : Un dictionnaire qui contient les clés et les valeurs de d1 et d2. Si
une clé existe dans les deux dictionnaires, la valeur du second dictionnaire
sera utilisée.
3. Supprimer les doublons d’une liste :
— Entrée : Une liste lst ;
— Sortie : Une liste sans doublons
4. Déterminer les clés manquantes d’un dictionnaire par rapport à un ensemble de
clés :
— Entrée : Un dictionnaire d et un ensemble keyst ;
— Sortie : Un ensemble des clés manquantes dans d par rapport à keys
5. Trouver les valeurs associées à une liste de clés dans un dictionnaire :
— Entrée : Un dictionnaire d et une liste de clés keys ;
— Sortie : Une liste des valeurs associées à keys dans le dictionnaire d
■
Exercise 5.2 — Fonctions de Hachage. Une fonction de hachage est une fonction
mathématique qui prend en entrée une donnée de taille quelconque (par exemple, une
chaîne de caractères ou un nombre) et la transforme en une valeur numérique de taille
fixe appelée "hash". La fonction de hachage est conçue pour être rapide à calculer, et
pour que deux entrées différentes ne donnent jamais le même hash.
Les fonctions de hachage sont utilisées dans de nombreux domaines, tels que
la sécurité informatique (par exemple, pour stocker des mots de passe sécurisés), la
compression de données (par exemple, pour trouver rapidement des doublons dans les
données) et les structures de données telles que les tables de hachage (où les entrées
sont stockées en fonction de leur hash).
5.7 Exercices 97
∀x ̸= y ⇒ f (x) ̸= f (y)
Les fonctions de hachage sans collision sont utilisées pour assigner un code numé-
rique unique à chaque élément d’une structure de données, telle qu’un dictionnaire.
Voici ci-dessous quelques exemples de fonctions de hachage simples :
Exemples
— Fonction de hachage de somme : cette fonction de hachage consiste à
additionner les codes ASCII de chaque caractère d’une chaîne de caractères
pour obtenir un code de hachage unique. Par exemple, pour la chaîne
’hello’, la fonction de hachage serait 104 + 101 + 108 + 108 + 111 = 532.
— Fonction de hachage de multiplication : cette fonction de hachage consiste
à multiplier chaque code ASCII d’une chaîne de caractères par un nombre
primaire. Par exemple, pour la chaîne ’hello’, la fonction de hachage
pourrait être 104 * 101 * 108 * 108 * 111 = 7438790400.
— Fonction de hachage de rotation : cette fonction de hachage consiste à
effectuer une opération de rotation sur les codes ASCII des caractères
d’une chaîne de caractères. Par exemple, pour la chaîne ’hello’, la fonction
de hachage pourrait être (104 « 1) + (101 « 2) + (108 « 3) + (108 « 4) +
(111 « 5) = 2049369601.
Questions :
1. Un dictionnaire dict en python peut avoir une liste comme clé ? justifier votre
réponse ?
2. les fonctions ci-dessus sont elles sans collisions ?
3. Programmer en python ces fonctions de Hachage ?
4. Comment peut-on utiliser ces fonctions pour stocker les données dans une liste
de taille fixe n ∈ N∗
5. écrire une fonction python qui permet calculer de "hacher" les noms des élèves
d’une classe, les stockes (haches) dans une listes et retourne cette liste.
6. écrire une fonction python qui renvoie True si un élève (nom) est dans une classe
donnée et False sinon.
■
Exercise 5.3 — Dict et set en Python. 1. Écrivez une fonction qui prend un dic-
tionnaire comme entrée et renvoie un nouveau dictionnaire qui inverse les clés et
les valeurs.
2. Écrivez une fonction qui prend un dictionnaire et un ensemble comme entrée et
renvoie un nouveau dictionnaire qui contient uniquement les clés présentes dans
l’ensemble.
98 Chapitre 5. Dict et Set
3. Écrivez une fonction qui prend deux dictionnaires comme entrée et renvoie un
ensemble qui contient les clés qui sont présentes dans les deux dictionnaires.
4. Écrivez une fonction qui prend un dictionnaire comme entrée et renvoie une liste
triée des valeurs.
5. Écrivez une fonction qui prend un ensemble comme entrée et renvoie un diction-
naire qui mappe chaque élément de l’ensemble à son nombre d’occurrences dans
l’ensemble.
■
Exercise 5.4 — Matrice creuse.. Une matrice creuse(sparse en anglais) est une
matrice comportant majoritairement des coefficients nuls. Autrement dit, le pourcentage
des coefficients non nuls est faible. Une image binaire contenant les codes 0 et 1 (0 pour
la couleur dominante et 1 correspondant aux pixels informatifs) peut être considérée
comme matrice creuse.
Il est ridicule de mémoriser tous les m x n coefficients d’une matrice de deux
dimensions (n,m). Il suffit d’en mémoriser les coefficients non nuls.
Nous avons déjà vu qu’une matrice M = (ai j )(i<n),( j<m) peut être représentée par
une liste de listes. Par exemple, la matrice :
0 1 0 0
M = 4 0 0 7
0 0 0 11
.
Afin d’économiser beaucoup de mémoire, On représente une telle matrice par un
dictionnaire dont les couples (key, value) sont ((i, j), ai j ) où ai j est l’élément de la
matrice d’indice i et j. Ainsi M[1,3]=7 ou bien M[(1,3)]=7 est l’élément M[1][3] dans
la notation de liste.
1. Écrire une fonction qui parcourt une liste de listes, et qui en construit le diction-
naire correspondant, avec l’omission des valeurs égales à zéro.
2. Écrire la conversion inverse.
■
P = {0 : 1, 1 : 2, 10000 : 3}
5.7 Exercices 99
Répondre aux questions du problème 2 mais dans le sens où les polynômes sont
codés par un dictionnaire { d : c} pour chaque coefficient c de P non nul associé au
degré d. ■
Exercise 5.6 — PILE et FILE. Coder les fonctions primitives des piles et des files en
utilisant un dictionnaire comme support de stockage. ■
Température = {
"France":[6, 5, 8, 12, 15, 17, 21, 22, 18, 9, 8, 6],
"Maroc":[16, 12, 18, 32, 28, 35, 43, 45, 35, 26, 25, 16]
}
Mois = ["Janvier","Février", ... ,"Décembre"]
températures qui retourne dans quel mois la température moyenne de tous les pays
est la même(avec une tolérance d’un degré).
III
Les structures de données
arborescentes
Bibliography . . . . . . . . . . . . . . . . . . . . . 127
Articles
Books
Misc
Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
6. Les Fichiers de textes
6.1 Présentation
En programmation, la saisie et l’affichage de données sont très importants : c’est le
moyen de communication directe entre le programmeur et l’utilisateur final. Nous avons
utilisé jusqu’à maintenant la fonction de saisie input() et la fonction d’affichage sur écran
print(). Cependant, la saisie au clavier est fastidieux, notamment quand on doit répéter
l’exécution d’un programme avec les mêmes données. En outre, les données saisies ne
sont pas conservées à long terme car ses données sont chargées par le compilateur dans la
mémoire volatile de l’ordinateur.
La sauvegarde de données sur un support de stockage permanent est cruciale en
archivage et en science de manipulation de données : à titre d’exemple, sauvegarder
les traitement et les commandes des clients d’une entreprise et archivé l’historique des
opérations de différents clients.
Ce chapitre présente les fonctions et les méthodes qui permettent de manipuler les
données dans les objets fichier texte en Python.
Remarque :
le curseur est un entier qui indique le nombre de caractères lus. Donc, il faut
distinguer le curseur (int) et l’objet graphique qui matérialise cet entier
(une barre verticale | qui clignote.
1. file : le chemin absolu ou relatif au répertoire courant de fichier à ouvrir sur le disque.
Le chemin est donné sous forme d’une valeur de type str
2. mode : est un paramètre optionnel qui permet de spécifier le mode d’ouverture. Par
défaut, la valeur ’r’ permet d’ouvrir le fichier en mode lecture. Voici une liste des
autres modes disponible :
valeur description
’r’ Lecture (par défaut) et le curseur est placé au
début (0)
’w’ Écriture (avec remise à zéro : fichier est écrasé
si déjà existant) et le curseur est placé au début
’x’ Création exclusive (erreur si fichier déjà existant)
et le curseur est placé au début
’a’ Écriture (avec ajout à la fin) le curseur est placé
à la fin (EOF)
’b’ Mode binaire
’t’ Mode texte (par défaut)
’+’ ouvre en modification (lecture et écriture)
Le mode ’r’ est synonyme à ’rt’, c’est à dire un fichier texte ouvert en mode lecture
(read). On peut ouvrir un fichier binaire avec le mode ’b’ (’br’, ’bw’, ...). Cependant,
le programme officiel de classe prépas ne couvre que les fichiers textes (titre du
chapitre).
3. buffering : est un paramètre facultatif utilisé par défaut pour définir la politique
de mis en mémoire tampon. La taille de tampon est choisie par une heuristique
essayant de déterminer la taille des blocs du système sous-jacent en utilisant la
constante io.DEFAULT_BUFFER_SIZE. Sur de nombreux systèmes d’exploitations,
le tampon sera de 4096 ou 8192 octets.
4. Encoding : est le nom de l’encodage utilisé pour encoder ou décoder le fichier. Il doit
seulement être utilisé en mode texte. L’encodage par défaut dépend de la plateforme
(ce que locale.getpreferredencoding() donne), mais n’importe quel encodage de texte
pris en charge par Python peut être utilisé.
5. errors : une chaîne optionnel qui permet de spécifier comment les erreurs de l’en-
codage et de décodage sont gérées : la valeur ’strict’ permet de lever une exception
ValueError si une erreur de l’encodage est rencontré. (d’autre valeurs sont existent,
il suffit de voir la documentation officielle 1
6. newline : contrôle le mode retour à la ligne universel. Il peut être None, ”, ’\n’, ’\r’,
et ’\r\n’. Sur de nombreux système, ’\n’ est le séparateur de lignes par défaut.
7. closefd : : Quand on ouvre un fichier, celui-ci est attaché à un fichier système identifié
par un entier appelé descripteur de fichier (fd). L’ensemble des fichiers système
ouverts sont maintenu par le système dans une table appelé table de descripteur. On
peut, en python, spécifier le descripteur au lieu du chemin. Si closedfd=False alors
ce descripteur est gardé dans la table des descripteurs même si le fichier renvoyé est
fermé par le programmeur.
8. opener : paramètre facultatif qui renvoie un descripteur de fichier ouvert. Ceci est
important si on veut rediriger la sortie standard de print vers un fichier au lieu de
l’écran.
1. voir https ://docs.python.org/fr/3/library/functions.html#open
106 Chapitre 6. Les Fichiers de textes
D’une manière plus simple, pour ouvrir un fichier, il suffit de préciser deux choses : le
chemin et le mode. Le renvoi de open() est un objet fichier qu’il faut choisir son nom :
L’exemple qui suit permet de créer un fichier ’data.csv’ dans le répertoire courant s’il
n’existe pas :
Notons bien que la méthode close() complète et termine les transferts des blocs de don-
nées vers les fichiers sur le support secondaire en cas d’écriture ou d’ajout ou modification
de données, et libère les zones de mémoires (tampons) associées aux fichiers. Cependant,
on peut ouvrir, traiter et fermer le fichier sans appeler la fonction close() avec la syntaxe
suivante :
Notons également que la clause with permet d’ouvrir simultanément plusieurs fichiers
selon la syntaxe suivante :
try:
file=open(’data.csv’,’r’)
...
except Exception ex:
print("Erreur d’ouverture:")
print(ex)
file.close()
la méthode readline
Definition 6.3.2 readline() : permet de renvoyer une ligne de type "str"(le caractère ’\n’
est inclus) et positionne le curseur sur la ligne suivante. Le code suivant permet de lire
la première ligne :
la méthode readlines
Definition 6.3.3 readlines() : permet de renvoyer une liste contenant les lignes de fichier
et positionne le curseur en fin du fichier. Le code suivant permet d’afficher cette liste :
R Pour ajouter une ligne et positionner le curseur sur la ligne suivante, il faut ajouter
explicitement le caractère "\n" en fin de cette ligne.
la méthode writelines
Definition 6.3.5 writelines() :permet d’écrire directement le contenu d’une liste. Nous
devons quand même insérer le caractère \n pour que le saut de ligne soit effectif dans le
fichier. Le code suivant permet d’insérer une liste de lignes à la fin du fichier "note.txt" :
6.4 Exercices
Exercise 6.1 On dispose d’un fichier texte "notes.txt" dont lequel on a stocké les notes
d’une classe des étudiants selon le format suivant :
CNE, Nom, P r énom , DS1 , DS2 , DL , TD , TP
L1245786214 , Nourman , A l i , 1 2 , 8 , 1 4 , 1 2 , 13
L1011345215 , Tourman , Nora , 1 0 , 1 3 , 1 2 , 1 1 , 14
...
Développer une application python qui permet de lire ce fichier, calcule la moyenne
de chaque élève et stocke le résultat dans un autre fichier "result.txt" dont le format :
CNE, Nom P r énom , Moyenne , Appr é c i a t i o n
L1245786214 , Nourman A l i , 1 0 . 9 0 , Moyen
L1011345215 , Tourman , Nora , 1 2 . 0 5 , A s s e z B i e n
...
régression qui cherche à établir une relation linéaire entre une variable Y, dite expliquée, et
une ou plusieurs variables, dites explicatives X.
A titre d’exemple, si Y représente la tension artérielle et X est l’âge d’un individu, la
régression linéaire consiste à étudier la relation entre la variable Y et la variable X, c’est à
dire expliquer la tension à partir de l’âge d’un individu
Préparation de données
On utilisera un fichier texte pour stocker les données du modèle et on définira des
fonctions intermédiaire pour lire et écrire dans un fichier texte. Les données à traiter sont
numériques et il faut, donc, les nettoyer (convertir texte en float, supprimer les espaces et
les caractères d’échappement) afin de construire les listes X et Y.
1. Écrire un programme python permettant de créer le fichier ’courbe.txt’ contenant les
éléments suivants :
(a) 10 : nombre de points du fichier ;
(b) 25 ; 10.9 : abscisse et ordonnée du premier point
(c) 20 ; 9.3
(d) 15 ; 8.2
(e) 12 ; 7.5
(f) 9 ; 6.2
(g) 6 ; 5.8
(h) 3 ; 4.2
(i) 0 ; 3.9
(j) -3 ; 2.8
(k) -6 ; 2 : abscisse et ordonnée du dernier point
Les valeurs numériques sont données à titre d’exemple et il faut les lire à partir du
clavier. Notez bien que les xi et yi sont séparés par point virgules ( ;) et chaque ligne
contient uniquement un seul point xi ; yi sauf la première ligne qui indique le nombre
total des points
2. Écrire un programme Python permettant d’ouvrir le fichier en lecture, de le lire et
de construire la liste X des abscisses et la liste Y des ordonnées contenues dans ce
fichier. X et Y sont deux listes.
3. Écrire un programme Python permettant de représenter les points sur une figure.
et
b = y − ax
110 Chapitre 6. Les Fichiers de textes
i=n i=n
1 1
où y = n ∑ yi est la moyenne des yi et x = n ∑ xi la moyenne des xi
i=1 i=1
5. Écrire un programme Python permettant de calculer les paramètres a et b correspon-
dant aux points expérimentaux de la question 2. La fonction prédéfinie sum est non
autorisé et il fallait écrire vos propres fonctions intermédiaire
6. Écrire un programme Python permettant de représenter graphiquement la fonction
ymod élisé = ax + b
On fournit les instructions Python pour la gestion des fichiers :
— f=open(’fichier.txt’, ’w’) : où fichier.txt désigne le nom du fichier. le mode d’ouver-
ture peut être ’w’ pour write, ’r’ pour read ou ’a’ pour append.
— f.readline() : lecture d’une ligne du fichier f
— ’\n’ : caractère d’échappement : saut de ligne
— c.strip() : renvoie une chaîne sans les espaces et les caractères d’échappement en
début et en fin de la chaîne c
— c.split(sep=’ ;’) renvoie une liste de mots qui sont séparés par ’ ;’
— f.write(’exemple’) : écrit dans le fichier f la chaîne de caractères ’exemple’
— f.close() : ferme le fichier f
7. calcul scientifique
Dans de ce chapitre, nous allons écrire les premières algorithmes numérique qui tra-
vaillent sur des nombres flottants et non plus sur les entiers. Les nombres réels de type float
comporte nombreuse approximations : conversion entre nombres décimaux et nombres
dyadiques, calculs approchés... avec pour conséquences les phénomènes d’arrondis, d’ab-
sorption et d’annulation .
Vecteurs
112 Chapitre 7. calcul scientifique
On peut facilement définir des arrays contenants des séquences de valeurs numériques
avec la fonction arange() :
>>> # 1 p a r a m e t r e : donne l a l o n g u e u r de l a s e q u e n c e ( en p a r t a n t de z e r o )
>>> v=np . a r a n g e ( 3 )
>>> v
[0 ,1 , 2]
>>> # 2 p a r a m e t r e s : d e b u t e t f i n de l a s e q u e n c e
>>> # ( a t t e n t i o n , l e s i n d i c e s commencent a z e r o , l a d e r n i e r e v a l e u r e s t
donc e x c l u e )
>>> v=np . a r a n g e ( 3 , 9 )
array ([3 , 4 , 5 , 6 , 7 , 8])
>>> # 3 p a r a m e t r e s : d é b u t , f i n de l a s e q u e n c e e t i n c r e m e n t ( i c i l e p a s
e s t de deux )
>>> v=np . a r a n g e ( 3 , 9 , 2 )
>>> v
array ([3 , 5 , 7])
>>> # é g a l e m e n t a v e c d e s v a l e u r s non e n t i è r e s
>>> v = np . a r a n g e ( 0 , 3 2 , np . p i )
>>> v
array ([ 0. , 3.14159265 , 6.28318531 , 9.42477796 ,
12.56637061 , 15.70796327 , 18.84955592 , 21.99114858 ,
25.13274123 , 28.27433388 , 31.41592654])
>>> a=np . a r r a y ( [ 1 . 2 , 2 . 5 , 3 . 2 , 1 . 8 ] )
>>> a= a p p e n d ( a , 1 0 )
>>> a
array ([ 1.2 , 2.5 , 3.2 , 1.8 , 10. ])
>>> # c o n c a t é n a t i o n 2 v e c t e u r s
>>> x=np . a r r a y ( [ 1 , 2 , 5 , 6 ] )
>>> y=np . a r r a y ( [ 2 , 1 , 7 , 4 ] )
>>> z=np . a p p e n d ( x , y )
array ([1 , 2 , 5 , 6 , 2 , 1 , 7 , 4])
>>> # s u p p r e s s i o n v i a i n d i c e
>>> b=np . d e l e t e ( a , 2 )
array ([ 1.2 , 2.5 , 1.8 , 10. ])
Matrices
Une matrice est un tableau (array) à 2 dimensions (tableau de tableaux).
>>> # c r e a t i o n d ’ une m a t r i c e }
>>> A = np . a r r a y ( [ [ 1 , 2 , 3 ] , [ 4 , 5 , 6 ] ] )
>>> A
array ([[1 , 2 , 3] ,
7.1 Numpy, matplotlib et scipy 115
[4 , 5 , 6]])
>>>> A, d t y p e # t y p e d e s é l é m e n t s de l a m a t r i c e
dtype ( ’ int64 ’ )
>>> A . s h a p e # r e n v o i e un t u p l e ( num . l i g n e s , num . c o l o n n e s )
(2 , 3)
>>> A . s i z e # nombre t o t a l e de v a l e u r s
6
>>> B= np . a r r a y ( [ [ 1 . 2 , 2 . 5 ] , [ 3 . 2 , 1 . 8 ] ] )
array ([[1.2 , 2.5] ,
[3.2 , 1.8]])
>>> t y p e ( B )
< c l a s s ’ numpy . n d a r r a y ’ >
>>> B . d t y p e
dtype ( ’ f l o a t 6 4 ’ )
>>> B . s h a p e
(2 , 2)
>>> # m a t r i c e s de v a l e u r s i d e n t i q u e s , p a r ex . p o u r une i n i t i a l i s a t i o n
>>> C=np . z e r o s ( ( 2 , 1 ) ) # a t t e n t i o n , d o u b l e p a r e n t è s e
>>> C
array ( [ [ 0 . ] ,
[0.]])
>>> p r i n t ( "A= " , A)
A= [ [ 1 2 3 ]
[4 5 6 ]]
>>> # p l u s g é n é r a l e m e n t
>>> C = np . f u l l ( ( 2 , 4 ) , f i l l _ v a l u e = 0 . 3 )
array ([[0.3 , 0.3 , 0.3 , 0.3] ,
[0.3 , 0.3 , 0.3 , 0.3]])
>>> # c r é a t i o n d ’ une m a t r i c e 3 x3 de v a l e u r s a l é a t o i r s d ’ une
d i s t r i b u t i o n uniforme sur [0 , 1]
>>> D=np . random . r a n d ( 3 , 3 )
>>> D
array ([[0.59597357 , 0.78596938 , 0.02071907] ,
[0.75553271 , 0.02298006 , 0.71780333] ,
[0.13262969 , 0.77058417 , 0.81046751]])
>>> # c r é a t i o n d ’ une m a t r i c e 2 x4 d ’ e n t i e r s a l é a t o i r e s e n t r e 0 e t 5
exclu .
>>> E=np . random . r a n d i n t ( 5 , s i z e = ( 2 , 4 ) )
array ([[4 , 4 , 0 , 3] ,
[2 , 1 , 0 , 1]])
On peut redimensionner une matrice par ajout d’une ligne ou d’une colonne
>>> # m a t r i c e de v a l e u r s
>>> A = np . a r r a y ( [ [ 1 . 2 , 2 . 5 ] , [ 3 . 2 , 1 . 8 ] , [ 1 . 1 , 4 . 3 ] ] )
>>> A
array ([[1.2 , 2.5] ,
[3.2 , 1.8] ,
[1.1 , 4.3]])
>>> # a j o u t e r une l i g n e : A c c o l e r l e v e c t e u r b en t a n t que n o u v e l l e
l i g n e ( a x i s = 0 ) de l a m a t r i c e A
>>> b = np . a r r a y ( [ [ 4 . 1 , 2 . 6 ] ] )
>>> b
array ([[4.1 , 2.6]])
116 Chapitre 7. calcul scientifique
>>> C = np . a p p e n d (A, b , a x i s = 0 )
>>> C
array ([[1.2 , 2.5] ,
[3.2 , 1.8] ,
[1.1 , 4.3] ,
[4.1 , 2.6]])
>>> # a j o u t e r une c o l o n n e : A c c o l e r l e v e c t e u r d en t a n t que n o u v e l l e
c o l o n n e ( a x i s = 1 ) de l a m a t r i c e A
>>> d = np . a r r a y ( [ [ 7 . 8 ] , [ 6 . 1 ] , [ 5 . 4 ] ] )
>>> D = np . a p p e n d (A, d , a x i s = 1 )
>>> D
array ([[1.2 , 2.5 , 7.8] ,
[3.2 , 1.8 , 6.1] ,
[1.1 , 4.3 , 5.4]])
# i n s e r t i o n : I n s e r t i o n de b en t a n t que n o u v e l l e l i g n e ( a x i s = 0 ) à l a
p o s i t i o n numé r o 1
>>> E=np . i n s e r t (A, 1 , b , a x i s = 0 )
>>> E
array ([[1.2 , 2.5] ,
[4.1 , 2.6] ,
[3.2 , 1.8] ,
[1.1 , 4.3]])
# suppression
>>> F=np . d e l e t e (A, 1 , a x i s = 0 )
>>> F
array ([[1.2 , 2.5] ,
[1.1 , 4.3]])
# m o d i f i e r l a d i m e n s i o n d ’ une m a t r i c e e x i s t a n t e p a r c o u r t l e s donn é e s
l i g n e s par ligne
>>> G=np . r e s i z e (A, ( 2 , 3 ) )
>>> G
array ([[1.2 , 2.5 , 3.2] ,
[1.8 , 1.1 , 4.3]])
>>> A = np . a r r a y ( [ [ 1 , 2 ] , [ 3 , 4 ] , [ 5 , 6 ] ] )
>>> B = np . a r r a y ( [ [ 1 , 2 ] , [ 3 , 4 ] ] )
>>> A
array ([[1 , 2] ,
[3 , 4] ,
[5 , 6]])
>>> B
array ([[1 , 2] ,
[3 , 4]])
>>> A . d o t ( B ) # m u l t i p l i c a t i o n m a t r i c i e l l e
array ( [ [ 7 , 10] ,
[15 , 22] ,
[23 , 34]])
>>> A @ B # idem : m u l t i p l i c a t i o n m a t r i c i e l l e a v e c @
array ( [ [ 7 , 10] ,
[15 , 22] ,
[23 , 34]])
— Matrice triangulaire
>>> # d é f i n i r une m a t r i c e c a r r é e
>>> M = np . a r r a y ( [ [ 1 , 2 , 3 ] , [ 1 , 2 , 3 ] , [ 1 , 2 , 3 ] ] )
>>> l o w e r =np . t r i l (M) # m a t r i c e t r i a n g u l a i r e i n f é r i e u r e
>>> l o w e r
array ([[1 , 0 , 0] ,
[1 , 2 , 0] ,
[1 , 2 , 3]])
>>> u p p e r =np . t r i u (M) # m a t r i c e t r i a n g u l a i r e s u p é r i e u r
>>> u p p e r
array ([[1 , 2 , 3] ,
[0 , 2 , 3] ,
[0 , 0 , 3]])
— Matrice diagonale
>>> # d é f i n i r une m a t r i c e c a r r é e
>>> M = np . a r r a y ( [ [ 1 , 2 , 3 ] , [ 1 , 2 , 3 ] , [ 1 , 2 , 3 ] ] )
>>> d = np . d i a g (M) # e x t r a i r e l a d i a g o n a l e
>>> d
array ([1 , 2 , 3])
>>> M
array ([[1 , 2 , 3] ,
[1 , 2 , 3] ,
[1 , 2 , 3]])
>>> d
array ([1 , 2 , 3])
>>> M
array ([[1 , 2 , 3] ,
[1 , 2 , 3] ,
[1 , 2 , 3]])
>>> # c r é e r une m a t r i c e d i a g o n a l e à p a r t i r du v e c t e u r
>>> D=np . d i a g ( d )
>>> D
array ([[1 , 0 , 0] ,
[0 , 2 , 0] ,
[0 , 0 , 3]])
— Matrice identité
>>> I 3 =np . i d e n t i t y ( 3 )
>>> I 3
array ([[1. , 0. , 0.] ,
[0. , 1. , 0.] ,
7.1 Numpy, matplotlib et scipy 119
[0. , 0. , 1. ]] )
On utilise le sous-module linalg contenu dans Numpy pour les calculs d’algèbre linéaire.
>>> A=np . a r r a y ( [ [ 1 , 2 ] , [ 3 , 4 ] ] , d t y p e = f l o a t )
>>> A
array ([[1. , 2.] ,
[3. , 4.]])
>>> B=np . l i n a l g . i n v (A) # i n v e r s e de A
>>> B
array ([[ −2. , 1. ] ,
[ 1.5 , −0.5]])
>>> # c a l c u l e r l e d e t e r m i n a n t }
>>> d=np . l i n a l g . d e t (A)
>>> d
−2 .00 000 000 000 000 04
Résolution d’équations linéaires de type A.x = b, où A est une matrice, b et x deux vecteurs.
>>> # r é s o l u t i o n d ’ é q u a t i o n
>>> A=np . a r r a y ( [ [ 1 , 2 ] , [ 3 , 4 ] ] , d t y p e = f l o a t )
>>> b=np . a r r a y ( [ 1 . 7 , 1 . 0 ] )
>>> x =np . l i n a l g . s o l v e (A, b )
>>> x
array ([ −2.4 , 2.05])
1.0
2.0
3.0
120 Chapitre 7. calcul scientifique
4.0
>>> # somme d e s v a l e u r s d ’ une m a t r i c e
>>> s = 0
>>> f o r i i n r a n g e ( 0 , A . s h a p e [ 0 ] ) :
f o r j in range (0 , A. shape [ 1 ] ) :
s +=A[ i , j ]
>>> s
10.0
>>> np . sum (A)
10.0
D’une manière générale les fonctions plt.plot attendent des vecteurs/matrices, c’est à dire
des tableaux de points du plan. On commence par afficher la fonction sinus.
import m a t p l o t l i b . pylab as p l t
i m p o r t numpy a s np
x=np . l i n s p a c e ( − 5 , 5 , 1 0 0 )
p l t . p l o t ( x , np . s i n ( x ) ) # on u t i l i s e l a f o n c t i o n s i n u s de Numpy
p l t . x l a b e l ( " axe des a b c i s s e s " )
plt . ylabel ( " fonction sinus " )
p l t . show ( )
7.1 Numpy, matplotlib et scipy 121
** Graphique "Scatter plot" (nuage de points)** Commençons par créer des points à
afficher.
# c r é a t i o n en a b s c i s s e d ’ un e n s e m b l e de p o i n t s s u r l \ PYZsq {} i n t e r v a l l e
[1 ,25]
xs = range ( 1 , 25)
# en o r d o n n é , p o u r c h a q u e p o i n t x d a n s l ’ e n s e m b l e xs , on c a l c u l e l a
valeur 1/ x
ys = [ 1 / x f o r x i n xs ]
On peut combiner ce graphique avec un deuxième nuage de points. Créons d’autres points.
# # c e t t e f o i s p o u r c h a q u e p o i n t x d a n s xs , j ’ a f f i c h e l a v a l e u r 1 / ( 2 5 − x )
>>> z s = [ 1 / ( 2 5 − x ) f o r x i n x s ]
Pour ajouter une légende, des axes et un titre à notre graphique (qui peuvent inclure du
code :
122 Chapitre 7. calcul scientifique
import m a t p l o t l i b . pylab as p l t
xs = range ( 1 , 2 5 )
ys = [ 1 / x f o r x i n xs ]
zs = [1/(25 − x ) f o r x i n xs ]
p l t . s c a t t e r ( xs , ys , l a b e l = " y = 1 / x " )
p l t . s c a t t e r ( xs , zs , l a b e l = " y = 1 / ( 2 5 − x ) " )
x \ PYZcb { } } \ PY{ l + s + s 2 } { \ PYZdl { } } \ PY{ l + s + s 2 } { \ PYZdq { } } \ PY{ p } { ) }
plt . xlabel ( "x"
p l t . y l a b e l ( " Valeur " )
p l t . t i t l e ( "Mon p r e m i e r s c a t t e r p l o t "
p l t . legend ( )
p l t . show ( )
def f ( t ) :
r e t u r n np . exp ( t ) * np . c o s ( 2 * np . p i * t )
# d é f i n i t i o n d e s v e c t e u r s de p o i n t s
t 1 = np . a r a n g e ( 0 . 0 , 5 . 0 , 0 . 1 )
t 2 = np . a r a n g e ( 0 . 0 , 5 . 0 , 0 . 0 2 )
plt . figure (1)
p l t . subplot (221)
p l t . p l o t ( t 1 , f ( t 1 ) , " bo " , t 2 , f ( t 2 ) , " k " )
# bo = r o n d s b l e u e t k = c o u l e u r n o i r
p l t . subplot (222)
p l t . p l o t ( t 2 , np . c o s ( 2 * np . p i * t 2 ) , " r −− " )
# r −− = p e t i s t r a i t s r o u g e s
p l t . subplot (223)
p l t . p l o t ( t 2 , np . s i n ( 2 * np . p i * t 2 ) , " b− " )
# b− = t r a i t c o n t i n u b l e u
7.1 Numpy, matplotlib et scipy 123
Au cas où un seul sous-module sera utilisé, il est possible de l’importer comme suit :
import scipy . l i n a l g
# i m p o r t e r l e s o u s module a l g è b r e l i n é a i r e
Plusieurs méthodes fournissant une valeur approchée d’une intégrale sont implémentées
dans Scipy.
Par exemple romberg calcule une valeur approchée de l’intégral à l’aide de la méthode
de Romberg, trapz calcule une valeur approchée de l’intégral à l’aide de la méthode des
trapèzes, simps calcule une intégrale à l’aide de la méthode de Simpson.
124 Chapitre 7. calcul scientifique
Dans nos exemples on utilisera quad, (dblquad and tplquad) qui permettent de
calculer des intégrales simples, (doubles ou triples respectivement) avec une méthode non
spécifiée, optimisée par Python.
Une façon de calculer une intégrale avec Scipy, est donc de définir une fonction et puis
lui appliquer la méthode quad.
from s c i p y i m p o r t e i n t e g r a t e
>>># d é f i n i r une f o n c t i o n s i m p l e à i n t é g r e r
>>> d e f f ( x ) :
return x
>>> x _ l o w e r }=0 # b o r n e i n f é r i e u r e de l ’ i n t é g r a l e
>>> x _ u p p e r =1 # b o r n e s u p é r i e u r e de l ’ i n t é g r a l e
>>> v a l , a b s e r r = i n t e g r a t e . quad ( f , x _ l o w e r , x _ u p p e r )
>>> p r i n t " é v a l e u r de l ’ i n t é g r a l e = " , v a l , " e r r e u r en v a l e u r a b s o l u e = " ,
abserr )
v a l e u r de l ’ i n t é g r a l e = 0 . 5 , e r r e u r en v a l e u r a b s o l u e =
5 . 5 5 1 1 1 5 1 2 3 1 2 5 7 8 3 e −15
def f (x , a , b ) :
r e t u r n a * x ** 2+ b
a =2
b=1
I = i n t e g r a t e . quad ( f , 0 , 1 , a r g s = ( a , b ) )
p r i n t ( " I =" , I )
#resultat
I =(1.6666666666666667 , 1.8503717077085944 e −14)
On peut avoir besoin d’utiliser le symbol oo comme borne d’un intégral. Par exemple
Z oo
fn (x) = e−xt /t n dt.
1
def f ( t , n , x ) :
r e t u r n np . exp ( − x * t ) / t ** n
def expint (n , x ) :
r e t u r n i n t e g r a t e . quad ( f , 1 , np . i n f , a r g s = ( n , x ) )
PS. ll existe déjà une fonction predéfinie expn(n,x) dans le paquetage scipy.special (on
pourrait donc l’importer import scipy.special as special et utiliser special.expn(3,
1.0) dans l’exemple ci-dessus pour obtenir le même résultat.
Double intégration :
Z oo Z oo
I(n) = e−xt /t n dt dx.
0 1
def I ( n ) :
r e t u r n i n t e g r a t e . d b l q u a d ( lambda t , x : np . exp ( − x * t ) / t ** n , 0 , np . i n f ,
lambda x : 1 , lambda x : np . i n f )
p r i n t ( I ( 3 ) ) # " La v a l e u r de l ’ i n t é g r a l e e s t 1 / n "
print ( I (4) )
Articles
[7] E. Knuth D ONALD. “Fonction de hashage”. In : (oct. 2023).
Livres
[1] G. A LLAIRE. Analyse numérique et optimisation : une introduction à la modélisation
mathématique et à la simulation numérique. Ecole polytechnique : Mathématiques
appliquées. Editions de l’Ecole polytechnique, 2005. ISBN : 9782730212557. URL :
https://books.google.co.ma/books?id=vReEuE4margC.
[2] N. AUDFRAY et al. Informatique : MPSI, PCSI, PTSI, BCPST, MP, PC, PT, PSI,
TSI, TPC. Dunod, 2020. ISBN : 9782100816408. URL : https://books.google.
co.ma/books?id=7-33DwAAQBAJ.
[3] N. AUDFRAY et al. Informatique - Tronc commun MPSI-PCSI-PTSI-MP-PC-PSI-
PT. Ediscience, 2022. ISBN : 9782100849444. URL : https://books.google.co.
ma/books?id=sEuJEAAAQBAJ.
[4] T. AUDIBERT et A. O USSALAH. Informatique tronc commun - CPGE scienti-
fiques 1re et 2e années - Nouveaux programmes. Editions Ellipses, 2021. ISBN :
9782340055926. URL : https://books.google.co.ma/books?id=WCFEEAAAQBAJ.
[5] A. C AIGNOT et al. Informatique - Tronc commun : Prépas scientifiques - MPSI-
PCSI-PTSI-MP/MP*-PC/PC*-PSI/PSI*-PT/PT*... : Cours - Synthèse - Méthodes
détaillées - Exercices et sujets corrigés. Prépas scientifiques : Les essentiels. Vuibert,
2022. ISBN : 9782311213539. URL : https://books.google.co.ma/books?
id=K--cEAAAQBAJ.
128 Chapitre 7. calcul scientifique
Webographie
[8] Python Software F OUNDATION. Exceptions en Python. https://docs.python.
org/fr/3/tutorial/errors.html. Jan. 2024 (cf. page 106).
[11] Python Software F OUNDATION. Entré/Sortie en Python. https://docs.python.
org/fr/3/tutorial/inputoutput.html. Jan. 2024 (cf. page 104).
[15] Python Software F OUNDATION. Datat struct In Python. https://docs.python.
org/fr/3/tutorial/datastructures.html. Jan. 2024 (cf. pages 10, 19, 22).
Index
B fichier . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
bloc mémoire . . . . . . . . . . . . . . . . . . . . . . 104 filter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
find . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
C fonction récursive . . . . . . . . . . . . . . . . . . . 57
format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
capitalize . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
caractère d’échappement . . . . . . . . . . . . . 22 I
concaténation . . . . . . . . . . . . . . . . . . . . . . . 12
copy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16 identity . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
count . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 immuable . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
insert . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
D
J
dblquad . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
del . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 join . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
diag . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
dict . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 L
dot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
duplication . . . . . . . . . . . . . . . . . . . . . . . . . 12 lambda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
legend . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
E linspace . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
List . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
Entrée/Sortie . . . . . . . . . . . . . . . . . . . . . . 103 lower. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .24
130 INDEX
M tri à bulle . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
tril, triu . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
map . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 tuple . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
matrice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
max . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12 U
min . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
mutable . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 upper . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
N Z
Numpy, matplotlib et scipy . . . . . . . . . . 111 zip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
P
Pile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
plot . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
pop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
programmation modulaire . . . . . . . . . . . . 45
Q
quad . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
R
recherche dichotomique . . . . . . . . . . . . . . 36
recherche séquentielle . . . . . . . . . . . . . . . 35
remove . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
replace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
reverse . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
S
scatter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
set . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
slicing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
sort . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
split . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
str . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
strip . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
sum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
T
tampon mémoire . . . . . . . . . . . . . . . . . . . 104
transposé . . . . . . . . . . . . . . . . . . . . . . . . . . 117
tri par insertion . . . . . . . . . . . . . . . . . . . . . . 41
tri par sélection . . . . . . . . . . . . . . . . . . . . . 39