Récursivité: Exercices

publicité
MP{931, 932}
Lycée Masséna
Récursivité: Exercices
Exercice 1. Pour s’échauffer . Dans cet exercice, on ne se préoccupera pas de l’inéfficacité (en terme de complexité)
éventuelle des fonctions que l’on écrit.
1. Écrire une fonction récursive somme(n,m) calculant n + m, en supposant que n et m sont des entiers naturels,
en ne faisant que des additions de 1.
2. Écrire une fonction récursive terme_arit(n,r,u) calculant le terme d’indice n d’une suite arithémtique de
raison r et de premier terme u. Même question avec terme_geo(n,r,u) (n-ème terme d’une suite géométrique
de raison r et de premier terme u).
3. Écrire une fonction récursive calculant le PGCD de deux entiers positifs (non tous deux nuls) a et b par l’algorithme d’Euclide.
4. Écrire une fonction récursive renvoyant l’inverse d’une chaîne de caractères passée en argument. Par exemple :
>>> inverse("blabla")
'albalb'
>>> inverse("") #chaine vide
''
>>> inverse("ressasser")
'ressasser'
5. En déduire une fonction (non récursive) palindrome testant si une chaîne est égale à son inverse (elle renvoie
un booléen).
6. Reprendre la question précédente avec une fonction récursive, qui ne calcule pas la chaîne inverse.
7. Écrire une fonction récursive base10a2 prenant en entrée un entier positif N , et renvoyant l’écriture binaire de
N sous la forme d’une chaîne de caractères. On renverra la chaîne vide pour zéro.
>>> base10a2(35)
'100011'
Exercice 2. Écrire une fonction récursive sdc(n) retournant la somme des chiffres de l’entier supposé naturel passé
en argument.
>>> sdc(1234)
10
Exercice 3. Binôme de Newton. Écrire une fonction binom(n,p) prenant en paramètres deux entiers positifs et
calculant np , en utilisant la formule de Pascal. Que pensez-vous de l’efficacité pratique de l’algorithme ?
Exercice 4. Minimum local . On considère une liste L de taille n > 0. On dit qu’un élément L[i] de L est un minimum
local de la liste s’il vérifie les deux conditions suivantes :
— i = 0 ou (i > 0 et L[i] ≤ L[i − 1])
— i = n − 1 ou (i < n − 1 et L[i] ≤ L[i + 1])
Autrement dit, un élément est un minimum local s’il est plus grand que ces deux voisins, ou de son unique voisin s’il
est placé sur un bord (ou encore si c’est le seul élément d’une liste de taille 1...).
1. Justifier qu’une liste possède un minimum local.
2. Naïvement, comment rechercher un minimum local ? Quelle est la complexité dans le pire cas ?
3. En vous inspirant de la recherche dichotomique, écrire une fonction usant de récursivité recherchant un minimum
local de complexité O(log(n)) avec n la taille de la liste. On fera attention au coûts cachés : ainsi on ne fera pas
de recopie d’éléments, mais on privilégiera l’utilisation d’une fonction auxiliaire (récursive).
Exercice 5. Fonctions mutuellement récursives. Démontrer la terminaison et la correction des deux fonctions cidessous.
def pair(n):
if n==0:
return(True)
else:
return(impair(n-1))
Svartz
def impair(n):
if n==0:
return(False)
else:
return(pair(n-1))
Page 1/3
2015/2016
MP{931, 932}
Lycée Masséna
Exercice 6. Fonction M91 . On considère la fonction suivante :
def f(n):
assert n>=0
if n>100:
return n-10
else:
return f(f(n+11))
Montrer sa terminaison, et déterminer les valeurs prises par f .
Exercice 7. Algorithme de Strassen. On cherche à multiplier rapidement deux matrices carrées à coefficients dans un
anneau commutatif A quelconque, et on considérera les opérations dans A comme unitaires.
1. Quelle est, en nombre d’opérations dans A, la complexité du calcul du produit de deux matrices A et B de taille
n × n à coefficients dans A, à l’aide des formules classiques ? Écrire une fonction prod_matrices prenant en
entrée deux matrices qu’on supposera de même taille et qui retourne le produit. Une matrice est stockée sous la
forme de la liste de ses lignes, par exemple :

1
M = 4
7
2
5
8

3
6 
9
M=[[1,2,3], [4,5,6], [7,8,9]]
En particulier, on accède au coefficient en case (i, j) de M par M[i][j]. Attention, lignes et colones sont indexées
à partir de 0. On récupère la taille d’une matrice carrée via len(M).
2. Vérifiez les formules suivantes, valables pour deux matrices de taille 2, 2.
a1,1 a1,2
b1,1 b1,2
P 1 + P 4 − P5 + P7
P3 + P5
×
=
a2,1 a2,2
b2,1 b2,2
P2 + P4
P1 − P2 + P3 + P6
où :
P1
P2
P3
P4
P5
P6
P7
=
=
=
=
=
=
=
(a1,1 + a2,2 )(b1,1 + b2,2 )
(a2,1 + a2,2 )b1,1
a1,1 (b1,2 − b2,2 )
a2,2 (b2,1 − b1,1 )
(a1,1 + a1,2 )b2,2
(a2,1 − a1,1 )(b1,1 + b1,2 )
(a1,2 − a2,2 )(b2,1 + b2,2 )
3. En déduire un algorithme récursif (on ne demande pas de le coder !) pour multiplier deux matrices carrées, de
taille une puissance de 2, qui exploite une stratégie diviser pour régner. C’est l’algorithme de Strassen (1969).
4. Justifier que la complexité C(n) de l’algorithme vérifie (en nombre d’opérations dans A) :
n
C(n) = 7 × C
+ O(n2 )
2
5. Qu’en déduisez-vous sur la complexité de l’algorithme de Strassen ? (Il n’est pas très difficile de passer de n une
puissance de 2 à n quelconque).
6. Imaginons qu’on sache multiplier deux matrices de taille 3×3 avec p multiplications. Quel est la valeur maximale
de p qui permettrait de faire mieux (asymptotiquement) que l’algorithme de Strassen ?
Il est conjecturé que pour tout ε > 0, il existe un algorithme permettant le calcul de deux matrices n×n nécessitant
O(n2+ε ) opérations dans A. La meilleure borne connue aujourd’hui (obtenue en 2014 !) est ε = 0.3726639. La
question de la complexité du produit de deux matrices est un problème crucial : on peut montrer que de nombreux
problèmes (résolution de systèmes linéaires, inversion de matrices...) ont la même complexité. En pratique, seul
l’algorithme de Strassen est utilisable (pour faire mieux que l’algorithme naïf ) pour des tailles de matrices
réalistes. Le nombre minimal de multiplications nécessaires pour multiplier deux matrices carrées de taille 3 est
également un problème ouvert.
Svartz
Page 2/3
2015/2016
MP{931, 932}
Lycée Masséna
Exercice 8. Des fractales. On se donne la fonction cercle suivante, qui trace le cercle de centre (x, y) et de rayon r :
def cercle(x,y,r):
theta = np.linspace(0, 2*np.pi, 100)
X = r*np.cos(theta)+x
Y = r*np.sin(theta)+y
plt.plot(X,Y)
Elle suppose les modules matplotlib.pyplot et numpy importés, sous les noms classiques de plt et np. Remarquez
que np.cos et np.sin sont vectorielles : lorsqu’on les applique à un tableau numpy, on calcule un tableau de même
taille contenant les images par ces fonctions des éléments du tableau initial. Remarquez aussi qu’on peut facilement
multiplier toutes les entrées d’un tableau numpy par une valeur (ici r) ou toutes les translater d’une constante (x ou
y ici) pour obtenir de nouveaux tableaux. Écrire deux fonctions bulles1(n) et bulles2(n) permettant d’obtenir des
figures similaires à celles ci-dessous (qui résultent des appels bulles1(5) et bulles2(5)).
Le cas de base (n = 0) est celui du cercle unité. On utilisera à chaque fois des fonctions auxiliaires récursives. Remarque :
si vous voulez faire ce tracé chez vous, veillez à taper l’instruction plt.axis(’equal’) pour avoir des axes égaux,
c’est plus joli.
Exercice 9. Le problème des dames. On rappelle qu’au jeu d’échecs, on travaille sur un échiquier de taille 8 × 8. Deux
dames posées sur l’échiquier sont « en prise » si elles se trouvent sur la même colonne, la même ligne, ou la même
diagonale (au sens large). Le problème des 8 dames consiste à placer 8 dames sur un échiquier de sorte que deux
d’entre elles ne soient jamais en prise. La figure qui suit est un exemple de solution.
1. Écrire une fonction permettant de dénombrer toutes les solutions (il y en a 92).
2. Plus généralement, pour le problème des n dames sur un échiquier n × n, jusqu’à quel entier n peut-on espérer
obtenir une solution ?
À ma connaissance, le nombre de solutions n’est connu que jusqu’à n = 26, et vaut 22317699616364044 (le résultat date de 2009). Ce problème reste en grande partie ouvert : on ne connaît même pas d’équivalent asymptotique
au nombre de solutions.
Svartz
Page 3/3
2015/2016
Téléchargement