Apprendre la récursivité avec |
Table des matières
- Chapitre 1 Un programme itératif et sa version récursive
- Chapitre 2 Programmes avec plusieurs appels récursifs
- Chapitre 3 Solution des exercices et des programmes réalisant les télés
Index
Avant-propos
On a choisit ici de faire des programmes récursifs graphiques : lorsqu’ un
dessin est récursif on peut facilement voir dans ce dessin le même dessin
en plus petit et donc la récursivité se voit.
Comme exemple d’image récursive, on peut prendre un écran de télévision
sur lequel il y a un présentateur et une télévision qui diffuse la même
chaîne et sur cette télévision on peut voir un présentateur et une
télévision qui diffuse la même chaîne ou une chaîne différente
etc...
Il peut aussi y avoir un présentateur et plusieurs télévisions qui
diffusent la même chaîne ou des chaîne différentes...
Dans les exemples qui suivent on a :
avec tele1 on voit le présentateur de tele1 et l’écran de tele1,
avec tele2 on voit le présentateur de tele2 et l’écran de tele2,
avec tele12 on voit le présentateur de tele1 et l’écran de tele21,
avec tele21 on voit le présentateur de tele2 et l’écran de tele12.
python_compat(0)
onload
les programmes des solutions des exercices ainsi que ceux permettant de réaliser les télés sont a la fin du document dans le chapitre 3.
Chapitre 1 Un programme itératif et sa version récursive
1.1 Programme avec 1 seul appel récursif
1.1.1 Exemple1 : traduction d’un pour avec 1 appel récursif
On veut tracer une suite de cercles de centre et de rayon successivement
.. .
On a écrit un programme graphique itératif cerclesp(z0,r,n)
qui utilise pour cela l’instruction pour k de 1 jusque n faire...fpour
et une séquence L qui va contenir la suite des instuctions
graphiques à exécuter.
En mode Xcas
cerclesp(z0,r,n):={ local L,k; L:=NULL; pour k de 1 jusque n faire L:=L,cercle(z0,r); z0:=z0+3*r/2; r:=r/2; fpour; return L; }:;
onload
On peut aussi utiliser une liste L qui va contenir la suite des
instuctions graphiques à exécuter.
Pour cela on utilise la commande
append pour ajouter un élément à la liste L soit avec
l’instruction :
L:=append(L,cercle(z0,r));
soit avec l’instruction :
L.append(cercle(z0,r));
cerclesp(z0,r,n):={ local L,k; L:=[]; pour k de 1 jusque n faire L.append(cercle(z0,r)); z0:=z0+3*r/2; r:=r/2; fpour; return L; }:;
onload
On peut traduire ce programme en Python en tapant python(cerclesp).
def cerclesp(z0,r,n): # local L,k L=[] for k in range(1,n+1): L=append(L,cercle(z0,r)) z0=z0+3*r/2 r=r/2 return(L)
onload
On tape, si on veut voir les axes :
ou bien si on ne veut pas voir les axes :
Pour écrire la version récursive de ce programme il faut voir le dessin,
de paramètres z0,r,n, comme étant composé :
d’un grand cercle de centre z0 et de rayon r
et du même dessin de paramètres z0+3*r/2,r/2,n-1.
Pour que ceci soit correct, il faut bien sûr prévoir un test sur n :
par exemple si n>0 alors ....fsi;
On écrit la procédure récursive cerclesr1(z0,r,n) et on tape :
cerclesr0(z0,r,n):={ local L; L:=NULL; si n>0 alors L:=L,cercle(z0,r); L:=L,cerclesr1(z0+3*r/2,r/2,n-1); fsi; retourne L; }:;
onload
ou plus simplement sans utiliser de variables locales :
cerclesr1(z0,r,n):={ si n>0 alors retourne cercle(z0,r),cerclesr1(z0+3*r/2,r/2,n-1); fsi; retourne NULL; }:;
onload
ou bien on utilise comme test d’arrêt si n<=0 alors retourne NULL; fsi;
cerclesr2(z0,r,n):={ si n<=0 alors retourne NULL; fsi; retourne cercle(z0,r),cerclesr2(z0+3*r/2,r/2,n-1); }:;
onload
ou en syntaxe Python
def cerclesr0(z0,r,n) : #local L L=NULL if n>0 : L=L,cercle(z0,r),cerclesr2(z0+3*r/2,r/2,n-1) return(L)
onload
def cerclesr1(z0,r,n) : if n>0 : return(cercle(z0,r),cerclesr2(z0+3*r/2,r/2,n-1)) return(NULL)
onload
def cerclesr2(z0,r,n): if n<=0 : return(NULL) return(cercle(z0,r),cerclesr2(z0+3*r/2,r/2,n-1))
onload
1.1.2 Exemple2 : traduction d’un tantque
On peut vouloir faire un dessin similaire composé d’un certain nombre de
cercles avec comme condition d’arrêt : le rayon des cercles doit
être supérieur ou égal, par exemple, à 2.
On écrit alors un programme itératif qui utilise l’instruction
tantque ...faire ...ftantque et soit une séquence, soit une liste
L
cerclest(z0,r):={ local L; L:=[]; tantque r>=2 faire L.append(cercle(z0,r)); z0:=z0+3*r/2; r:=r/2; ftantque; retourne L; }:;
onload
ou en langage Python
def cerclest(z0,r): # local L L=[] while r>=2 : L.(append(cercle(z0,r))) z0=z0+3*r/2 r=r/2 return(L)
onload
Pour écrire la version récursive de ce programme il faut voir le dessin
(de paramètres (z0,r) avec r>=2) comme étant composé :
d’un cercle de centre z0 et de rayon r>=2 et
du même dessin plus petit (de paramètres (z0+3*r/2,r/2) avec
r/2>=2).
Donc, ce qui va changer c’est le test qui portera sur r.
cerclesr3(z0,r):={ local L; L:=NULL; si r>=2 alors L:=L,cercle(z0,r); L:=L,cerclesr3(z0+3*r/2,r/2); fsi; retourne L; }:;
onload
ou bien avec le test d’arrêt si r<2 alors retourne L; fsi;
cerclesr4(z0,r):={ si r<2 alors retourne NULL; fsi; retourne cercle(z0,r),cerclesr4(z0+3*r/2,r/2); }:;
onload
ou en langage Python
def cerclesr4(z0,r) : if r<2 : return NULL return cercle(z0,r),cerclesr4(z0+3*r/2,r/2)
onload
1.1.3 Exercice1
Écrire la version récursive du programme itératif suivant :
cerclexo1(z0,t,r,n) où z0 est l’affixe du centre du
grand cercle, t l’angle de rotation du dessin final, r est le rayon
du grand cercle et n est le nombre de cercles.
cerclexo1(z0,t,r,n):={ local L,k; L:=NULL; pour k de 1 jusque n faire L:=L,cercle(z0,r); z0:=z0+3*r*exp(i*(t+pi/4))/2; t:=t-pi/4; r:=r/2; fpour; retourne L; }:;
onload
1.2 Le test d’arrêt
On veut maintenant que dans le dernier cercle, il soit inscrit un hexagone
rempli de couleur rouge.
Pour cela, il faut écrire une instruction qui trace le cercle et l’hexagone
lorsque k=n.
cerclexo1h(z0,t,r,n):={ local L,k; L:=NULL; si n<=0 alors retourne L; fsi; pour k de 1 jusque n-1 faire L:=L,cercle(z0,r); z0:=z0+3*r*exp(i*(t+pi/4))/2; t:=t-pi/4; r:=r/2; fpour; L:=L,cercle(z0,r),isopolygone(z0,z0-r,-6,affichage=1+rempli); retourne L; }:;
onload
Écrire la version récursive de ce programme itératif.
Chapitre 2 Programmes avec plusieurs appels récursifs
On choisit dans cette section de ne dessiner que des cercles de rayon r>=5.
2.1 Programme avec 2 appels récursifs
Faire le programme cerclexo2r(z0,t,r),qui réalise les dessins qui
suivent (z0 est l’affixe du centre du grand cercle, t l’angle de
rotation du dessin final, r est le rayon du grand cercle) :
2.2 Programme avec 3 appels récursifs
Faire le programme cerclexo3r(z0,t,r) qui réalise les dessins qui
suivent (z0 est l’affixe du centre du grand cercle, t l’angle de
rotation du dessin final, r est le rayon du grand cercle):
Faire le programme cerclexo3rc(z0,t,r,c) qui réalise les dessins en
couleur qui suivent ((z0 est l’affixe du centre du grand cercle, t
l’angle de rotation du dessin final, r est le rayon du grand cercle) et
c est un entier désignant la couleur) :
Chapitre 3 Solution des exercices et des programmes réalisant les télés
3.1 Solution des exercices en syntaxe Xcas
cerclexo1r(z0,t,r,n):={ local L; L:=NULL; si n<=0 alors retourne L; fsi; L:=L,cercle(z0,r); L:=L,cerclexo1r(z0+3*r*exp(i*(t+pi/4))/2,t-pi/4,r/2,n-1); }:; cerclexo1rh(z0,t,r,n):={ local L; L:=NULL; si n<=1 alors L:=cercle(z0,r),isopolygone(z0,z0-r,-6,affichage=1+rempli); retourne L; fsi; L:=L,cercle(z0,r); L:=L,cerclexo1rh(z0+3*r*exp(i*(t+pi/4))/2,t-pi/4,r/2,n-1); }:; cerclexo2r(z0,t,r):={ local L:=NULL; L:=L,cercle(z0,r); si r<10 alors retourne L; fsi; L:=L,cerclexo2r(z0+3*r*exp(i*(t+pi/4))/2,t-pi/4,r/2); L:=L,cerclexo2r(z0+3*r*exp(i*(t+3*pi/4))/2,t+pi/4,r/2); }:; cerclexo3r(z0,t,r):={ local L:=NULL; L:=L,cercle(z0,r); si r<10 alors retourne L; fsi; L:=L,cerclexo3r(z0+3*r*exp(i*(t+pi/6))/2,t-pi/3,r/2); L:=L,cerclexo3r(z0+3*r*exp(i*(t+pi/2))/2,t,r/2); L:=L,cerclexo3r(z0+3*r*exp(i*(t+5*pi/6))/2,t+pi/3,r/2); }:; cerclexo3rc(z0,t,r,c1):={ local L:=NULL; L:=L,affichage(cercle(z0,r),rempli+c1); si r<5 alors retourne L; fsi; L:=L,cerclexo3rc(z0+3*r*exp(i*(t+pi/6))/2,t-pi/3,r/2,c1+2); L:=L,cerclexo3rc(z0+3*r*exp(i*(t+pi/2))/2,t,r/2,c1+2); L:=L,cerclexo3rc(z0+3*r*exp(i*(t+5*pi/6))/2,t+pi/3,r/2,c1+2); }:;
onload
3.2 Solution des exercices en syntaxe Python
def cerclexo1r(z0,t,r,n): # local L L=NULL if n<=0 : return(L) L=L,cercle(z0,r) L=L,cerclexo1r(z0+3*r*exp(i*(t+pi/4))/2,t-pi/4,r/2,n-1) def cerclexo1rh(z0,t,r,n): # local L L=NULL if n<=1 : L=cercle(z0,r),isopolygone(z0,z0-r,-6,equal('affichage',1+rempli)) return(L) L=L,cercle(z0,r) L=L,cerclexo1rh(z0+3*r*exp(i*(t+pi/4))/2,t-pi/4,r/2,n-1) def cerclexo2r(z0,t,r): # local L=NULL L=L,cercle(z0,r) if r<10 : return(L) L=L,cerclexo2r(z0+3*r*exp(i*(t+pi/4))/2,t-pi/4,r/2) L=L,cerclexo2r(z0+3*r*exp(i*(t+3*pi/4))/2,t+pi/4,r/2) def cerclexo3r(z0,t,r): # local L=NULL L=L,cercle(z0,r) if r<10 : return(L) L=L,cerclexo3r(z0+3*r*exp(i*(t+pi/6))/2,t-pi/3,r/2) L=L,cerclexo3r(z0+3*r*exp(i*(t+pi/2))/2,t,r/2) L=L,cerclexo3r(z0+3*r*exp(i*(t+5*pi/6))/2,t+pi/3,r/2) def cerclexo3rc(z0,t,r,c1): # local L=NULL L=L,affichage(cercle(z0,r),rempli+c1) if r<5 : return(L) L=L,cerclexo3rc(z0+3*r*exp(i*(t+pi/6))/2,t-pi/3,r/2,c1+2) L=L,cerclexo3rc(z0+3*r*exp(i*(t+pi/2))/2,t,r/2,c1+2) L=L,cerclexo3rc(z0+3*r*exp(i*(t+5*pi/6))/2,t+pi/3,r/2,c1+2)
onload
3.3 Les programmes des télés en syntaxe Xcas
tete1(z0,r):={ local L,A; L:=NULL; L:=L,cercle(z0,r); A:=point(z0+r*exp(i*pi/4)/2); L:=L,affichage(cercle(A,r/8),4+rempli); A:=point(z0+r*exp(3*i*pi/4)/2); L:=L,affichage(cercle(A,r/8),4+rempli); L:=L,arc(z0+point(r*exp(-3*i*pi/4)/2),z0+point(r*exp(-i*pi/4)/2),-pi/2); retourne L; }:; tele1(x1,y1,x2,n):={ local L; L:=NULL; si n<=0 alors retourne NULL; fsi; L:=L,affichage(rectangle(x1+i*y1,x2+i*y1,.5),0+epaisseur_ligne_2); L:=L,tete1((3*x1+x2)/4+i*(y1+(x2-x1)/6),(x2-x1)/6); L:=L,tele1((x1+x2)/2-(x2-x1)/50,y1+(x2-x1)/4-(x2-x1)/50,x2-(x2-x1)/50,n-1); }:; tete2(z0,r):={ local L,A; L:=NULL; L:=L,cercle(z0,r); A:=point(z0+r*exp(i*pi/4)/2); L:=L,affichage(cercle(A,r/8),2+rempli); A:=point(z0+r*exp(3*i*pi/4)/2); L:=L,affichage(cercle(A,r/8),2+rempli); L:=L,arc(z0+point(r*exp(-3*i*pi/4)/2),z0+point(r*exp(-i*pi/4)/2),pi/2); retourne L; }:; tele2(x1,y1,x2,n):={ local L; L:=NULL; si n<=0 alors retourne NULL; fsi; L:=L,affichage(rectangle(x1+i*y1,x2+i*y1,.5),1+epaisseur_ligne_2); L:=L,tete2((3*x1+x2)/4+i*(y1+(x2-x1)/6),(x2-x1)/6); L:=L,tele2((x1+x2)/2-(x2-x1)/50,y1+(x2-x1)/4-(x2-x1)/50,x2-(x2-x1)/50,n-1); }:; tele12(x1,y1,x2,n):={ local L; L:=NULL; si n<=0 alors retourne NULL; fsi; L:=L,affichage(rectangle(x1+i*y1,x2+i*y1,.5),0+epaisseur_ligne_2); L:=L,tete1((3*x1+x2)/4+i*(y1+(x2-x1)/6),(x2-x1)/6); L:=L,tele21((x1+x2)/2-(x2-x1)/50,y1+(x2-x1)/4-(x2-x1)/50,x2-(x2-x1)/50,n-1); }:; tele21(x1,y1,x2,n):={ local L; L:=NULL; si n<=0 alors retourne NULL; fsi; L:=L,affichage(rectangle(x1+i*y1,x2+i*y1,.5),1+epaisseur_ligne_2); L:=L,tete2((3*x1+x2)/4+i*(y1+(x2-x1)/6),(x2-x1)/6); L:=L,tele12((x1+x2)/2-(x2-x1)/50,y1+(x2-x1)/4-(x2-x1)/50,x2-(x2-x1)/50,n-1); }:;
onload
3.4 Les programmes des télés en syntaxe Python
def tete1(z0,r): # local L,A L=NULL L=L,cercle(z0,r) A=point(z0+r*exp(i*pi/4)/2) L=L,affichage(cercle(A,r/8),4+rempli) A=point(z0+r*exp(3*i*pi/4)/2) L=L,affichage(cercle(A,r/8),4+rempli) L=L,arc(z0+point(r*exp(-3*i*pi/4)/2),z0+point(r*exp((-(i))*pi/4)/2),-pi/2) return(L) def tele1(x1,y1,x2,n): # local L L=NULL if n<=0 : return(NULL) L=L,tete1((3*x1+x2)/4+i*(y1+(x2-x1)/6),(x2-x1)/6) L=L,affichage(rectangle(x1+i*y1,x2+i*y1,0.5),0+epaisseur_ligne_2) L=L,tele1((x1+x2)/2-(x2-x1)/50,y1+(x2-x1)/4-(x2-x1)/50,x2-(x2-x1)/50,n-1) def tete2(z0,r): # local L,A L=NULL L=L,cercle(z0,r) A=point(z0+r*exp(i*pi/4)/2) L=L,affichage(cercle(A,r/8),2+rempli) A=point(z0+r*exp(3*i*pi/4)/2) L=L,affichage(cercle(A,r/8),2+rempli) L=L,arc(z0+point(r*exp(-3*i*pi/4)/2),z0+point(r*exp((-(i))*pi/4)/2),pi/2) return(L) def tele2(x1,y1,x2,n): # local L L=NULL if n<=0 : return(NULL) L=L,tete2((3*x1+x2)/4+i*(y1+(x2-x1)/6),(x2-x1)/6) L=L,affichage(rectangle(x1+i*y1,x2+i*y1,0.5),1+epaisseur_ligne_2) L=L,tele2((x1+x2)/2-(x2-x1)/50,y1+(x2-x1)/4-(x2-x1)/50,x2-(x2-x1)/50,n-1) def tele12(x1,y1,x2,n): # local L L=NULL if n<=0 : return(NULL) L=L,tete1((3*x1+x2)/4+i*(y1+(x2-x1)/6),(x2-x1)/6) L=L,affichage(rectangle(x1+i*y1,x2+i*y1,0.5),0+epaisseur_ligne_2) L=L,tele21((x1+x2)/2-(x2-x1)/50,y1+(x2-x1)/4-(x2-x1)/50,x2-(x2-x1)/50,n-1) def tele21(x1,y1,x2,n): # local L L=NULL if n<=0 : return(NULL) L=L,tete2((3*x1+x2)/4+i*(y1+(x2-x1)/6),(x2-x1)/6) L=L,affichage(rectangle(x1+i*y1,x2+i*y1,0.5),1+epaisseur_ligne_2) L=L,tele12((x1+x2)/2-(x2-x1)/50,y1+(x2-x1)/4-(x2-x1)/50,x2-(x2-x1)/50,n-1)
onload