Académique Documents
Professionnel Documents
Culture Documents
Exercice 58. Donner la version itérative d’une procédure de calcul des termes de la suite de
F IBONACCI.
Solution. Le premier programme est la version générique, applicable à tout langage de pro-
grammation ; la version itérative à la mode « Python » met en œuvre l’affectation parallèle, ce
qui économise l’emploi d’une variable locale.
figIterGen.py fibIterPy.py
def fibo(n): def fibo(n):
a = 1 a = b = 1
b = 1 for i in range(n):
for i in range(n): a, b = a + b, a
t = a return b
a += b
b = t for n in range(12):
8155
return b print(fibo(n))
6368
for n in range(12):
print(fibo(n))
5:16
6.15
1.3 Complexité
25.8
définition d’une fonction sont bien établis, les étapes et instructions qui composent
l’algorithme sont toutes parfaitement déterminées, par leur nature et par les données
0833
pas toujours possible. Cette approche n’est pas souhaitable pour des programmes critiques,
scho
comme ceux qui gouvernent un calculateur embarqué pour la gestion d’un vol aéronautique,
ou le contrôle des équipements d’une centrale nucléaire.
univ.
Récursivité 231
Ces mesures, lorsqu’elles sont possibles, sont relatives à l’environnement matériel d’exécu-
tion du programme : architecture de l’ordinateur hôte, performances des processeurs, dispo-
nibilité de la mémoire en quantité suffisante...
8155
tures de données de la façon la plus pertinente pour l’algorithme qu’il doit mettre en
œuvre sous forme de programme. De fait, le seul outil dont dispose le programmeur est
6368
son propre raisonnement.
5:16
1.3.4 Avec quels outils ?
6.15
Les calculs sur ordinateur sont souvent l’occasion des « nombres réels machine », dont la maî-
trise des arrondis dans les calculs approchés doit être envisagée d’emblée avec précaution.
25.8
Néanmoins, nous nous limiterons ici à l’évocation de la complexité temporelle que nous no-
terons t (n).
195.
t (n) est une fonction de N dans R+ pour laquelle nous devons préciser la nature de n :
:
6811
10
Nous reprendrons l’exemple de la somme i.
P
i =1
I:211
somme.py
def somme(n): # (0)
CES
s = 0 # (1)
i = 1 # (2)
com:
return s # (6)
la
print(somme(10)) # (7)
scho
Chacune des instructions (i ) possède un coût d’exécution en temps que nous noterons c i
(c i ∈ R+ ) :
univ.
232 Programmation en Python pour les mathématiques
Selon que l’on considère que certaines opérations sont élémentaires ou non, on influe sur la
granularité et l’estimation du coût.
Nous pouvons maintenant effectuer notre calcul du coût d’exécution C(n) :
C(n) = c 1 + c 2 + c 3 + n × (c 4 + c 5 ) + c 6 + c 7 (5.9)
8155
= 2c 1 + c 3 + 2n (c 1 + c + ) + c 6 + c 7 (5.10)
= (2 (c 1 + c + )) n + (2c 1 + c 3 + c 6 + c 7 ) (5.11)
6368
= K1 n + K2
5:16
Nous constatons un coût affine en n. Selon la notation de L ANDAU, nous avons : C(n) = O(n).
Cette égalité exprime (nous sommes en présence de fonctions positives) :
6.15
∃K ∈ R+ , ∃n 0 ∈ N, ∀n ⩾ n 0 , C(n) ⩽ K × n.
25.8
Le coût d’exécution de notre fonction est majoré par une fonction affine de n, elle-même
majorée par une fonction linéaire. Le programmeur, par l’étude mathématique du problème,
195.
P
6811
Xn n(n + 1)
i=
2
8892
i =1
car le programme correspondant est lui en O(1), c’est-à-dire en temps constant, quelle que
soit la valeur de n.
166:
0833
rithme naïf ». Cela signifie que même si l’algorithme est correct, il est trop naïf pour être
réellement efficace.
rvox.
n−1 1
(n − p) = (n 2 − n).
X
2
univ.
p=1
Récursivité 233
Cependant, en moyenne, seule la moitié des éléments est décalée. Soit un décalage de
(p − 1)/2 éléments et donc une complexité en moyenne qui se calcule ainsi :
n 1 1
(p − 1) = (n 2 − n).
X
8155
p=2 2 4
Il s’agit d’une complexité en O(n 2 ) analogue à la complexité du tri par sélection. Cepen-
6368
dant, le tri par insertion présente un avantage certain : il peut être facilement mis en
œuvre pour insérer de nouvelles données dans un tableau déjà trié ou pour trier des va-
5:16
leurs au fur et à mesure de leur apparition (cas des algorithmes en temps réel où il faut
parfois exploiter une série de valeurs triées qui vient s’enrichir, au fil du temps, de nou-
6.15
velles valeurs). C’est l’un des seuls algorithmes de tri dont la complexité est meilleure
25.8
La complexité du tri rapide pour trier une liste de n éléments est égale à la complexité
pour le tri de p et de q éléments où p + q + 1 = n. Soit C(n) = C(p) + C(q) + const ant e.
:
6811
Dans le meilleur des cas, p = q = n/2, soit C(n) = 2C(q). On peut alors montrer que la
complexité en moyenne est en O(n · ln(n)).
8892
2 Spirale de pentagones
166:
Exercice 59. La spirale régulière ci-dessous est constituée de 50 pentagones (la longueur du
0833
plus grand côté étant 370 pixels), emboîtés de sorte qu’entre deux pentagones consécutifs
inscrits l’un dans l’autre, le côté du plus petit est une réduction de 10 % du côté du plus grand.
I:211
Solution.
pentagones.py
from math import *
from turtle import *
def pentagone(cote):
for n in range(5):
forward(cote)
left(72)
8155
pentagone(a)
d = coeff * a
6368
forward(d)
a_prime = sqrt((a-d)**2 + d**2 -2*(a-d)*d*(1-sqrt(5))/4)
angle = (180/pi) * acos((a_prime**2 + a**2 - 2*a*d)/(2*a_prime*(a-d)))
5:16
left(angle)
a = a_prime
6.15
25.8
up()
goto(-190,-210)
down()
195.
spirale(50, 370)
up()
:
6811
8892
3 Courbe du dragon
166:
dragon1.py
I:211
if niveau == 0:
forward(taille)
rvox.
else:
left(45)
la
dragon_gauche(taille/sqrt(2), niveau-1)
scho
right(90)
dragon_droite(taille/sqrt(2), niveau-1)
univ.
left(45)
Récursivité 235
dragon_droite(400, 12)
8155
6368
5:16
6.15
25.8
195. :
6811
dragon2.py
from math import sqrt
8892
if niveau == 0:
forward(taille)
0833
else:
left(45)
I:211
dragon_gauche(taille/sqrt(2), niveau-1)
right(90)
dragon_droite(taille/sqrt(2), niveau-1)
CES
left(45)
com:
forward(taille)
else:
la
right(45)
scho
dragon_gauche(taille/sqrt(2), niveau-1)
left(90)
dragon_droite(taille/sqrt(2), niveau-1)
univ.
236 Programmation en Python pour les mathématiques
right(45)
def figure():
color("red")
dragon_gauche(200, 10)
up()
goto(0, 0)
right(90)
down()
color("blue")
dragon_gauche(200, 10)
up()
goto(0, 0)
right(90)
down()
8155
color("green")
dragon_gauche(200, 10)
6368
up()
goto(0, 0)
right(90)
5:16
down()
color("gray")
dragon_gauche(200, 10) 6.15
up()
25.8
figure()
195. :
6811
4 Triangle de Sierpińsky
8892
et sierpinsky2.py :
0833
I:211
CES
com:
rvox.
la
scho
sierpinsky1.py
from turtle import *
univ.
Récursivité 237
8155
left(120)
6368
triangle(600, 5)
5:16
sierpinsky2.py
from turtle import *
6.15
def drapeau(longueur, niveau):
25.8
if niveau == 0:
down()
195.
cap = heading()
if cap == 0 or cap == 180:
:
6811
color("red")
if cap == 60 or cap == 240:
8892
color("green")
if cap == 120 or cap == 300:
color("blue")
166:
forward(longueur)
up()
0833
else:
drapeau(longueur/2, niveau-1)
I:211
left(120)
drapeau(longueur/2, niveau-1)
left(120)
CES
drapeau(longueur/2, niveau-1)
left(120)
com:
forward(longueur)
rvox.
drapeau(longueur, niveau)
scho
left(120)
univ.
triangle(600, 6)
238 Programmation en Python pour les mathématiques
8155
6368
5:16
4.2 Construction aléatoire 6.15
25.8
On peut obtenir aléatoirement le triangle de S IERPI ŃSKI par un algorithme très simple :
195.
Bien évidemment, il faut poursuivre l’algorithme assez longtemps sur le papier pour observer
0833
quelque chose, sans compter les segments [Mi Mi +1 ] uniquement utiles à la construction mais
qui encombrent le dessin. . .
I:211
un objet « point du plan », repéré par ses coordonnées cartésiennes et doté d’une couleur.
sierpinsky3.py
com:
delta = -300
scho
loupe = 600
univ.
class point(object):
Récursivité 239
def rouge(self):
self.couleur = "red"
8155
def vert(self):
self.couleur = "green"
6368
def bleu(self):
self.couleur = "blue"
5:16
def croix(self):
down() 6.15
for i in range(4):
25.8
forward(3)
backward(3)
195.
left(90)
up()
:
6811
def imprime(self):
goto(self.x*loupe + delta, self.y*loupe + delta)
8892
color(self.couleur)
self.croix()
166:
def figure(points):
0833
m = point(0.5, sqrt(3)/6)
com:
if points <= 0:
points = 200
rvox.
for i in range(points):
# obtention aléatoire du point suivant:
la
scho
m.milieu(a)
if alea == 1:
m.milieu(b)
if alea == 2:
m.milieu(c)
# obtention aléatoire de la couleur du point
alea = random.randrange(3)
if alea == 0:
m.rouge()
if alea == 1:
m.vert()
if alea == 2:
m.bleu()
m.imprime()
8155
up()
speed("fastest")
6368
figure(2000)
5:16
6.15
25.8
195. :
6811
8892
166:
On laisse en exercice l’écriture d’un programme pour l’obtention des sommes partielles de la
+∞
P ¡ 1 ¢i
I:211
série 4 .
i =1
La tortue LOGO du module standard « turtle » permet de donner aisément une interpréta-
CES