La recursivité sur des exemples

# Chapitre 7 La recursivité sur des exemples

## 7.1 Des spirales

### 7.1.1 Une spirale

Voici le début du dessin d’une spirale(90) :
On tape dans un éditeur de programmes :

    spirale(l):={
    si (l>10) alors
    avance(l);
    tourne_gauche 90;
    avance(l);
    tourne_gauche 90;
    spirale(l-10);
    fsi;
    }

On tape dans une ligne de commande :
`efface;spirale(100)`
On obtient :

### 7.1.2 Une spirale plus générale

On tape dans un éditeur de programmes :

    //chaque segment de la spirale est obtenu par similitude de rapport k
    //k=rapport et t=angle de rotation (externe)
    //n=nombre de segments a construire
    spirales(l,k,t,n):={
    pour j de 1 jusque n faire
    avance(l);
    tourne_gauche(t);
    l:=k*l;
    fpour;
    };

ou encore avec la recursivité

    //n=nombre de segments a construire=nombre d'appels recursifs
    spiraler(l,k,t,n):={
    si n>0 alors
     avance(l);
     tourne_gauche(t);
     spiraler(l*k,k,t,n-1);
    fsi;
    }:;

On tape par exemple dans une ligne de commande :
`spirales(90,0.8,60,20)`
ou
`efface;spiraler(90,0.8,60,20)`
On obtient :

## 7.2 Des arbres

### 7.2.1 Un arbre a deux branches

Un arbre est composé d’un tronc de hauteur h et de deux branches symétriques faisant 45 degrés avec le tronc et que l’on définit comme étant chacune un arbre de tronc h/2.
Pour le réaliser, on tape dans un éditeur de programmes :

    //tourne_gauche;arbre1(60)
    arbre1(h):={
    si (h<5) alors
    avance(h);
    recule(h);
    sinon
    avance(h);
    tourne_droite(45);
    arbre1(h/2);
    tourne_gauche(90);
    arbre1(h/2):
    tourne_droite(45);
    recule(h);
    fsi;
    }:;

On valide avec `OK` ou avec `F9`.
On tape par exemple dans une ligne de commande :
`efface;tourne_gauche;arbre1(60)`
On obtient :
Ou bien, on rajoute un paramètre n (la profondeur) pour faire le test d’arrêt, on tape on tape dans un éditeur de programmes :

    //tourne_gauche;arbre2(60,3)
    arbre2(h,n):={
    si (n==0) alors
    avance(h);
    recule(h);
    sinon
    avance(h);
    tourne_droite(45);
    arbre2(h/2,n-1);
    tourne_gauche(90);
    arbre2(h/2,n-1):
    tourne_droite(45);
    recule(h);
    fsi;
    }:;

On valide avec `OK` ou avec `F9`.
On tape par exemple dans une ligne de commande :
`efface;tourne_gauche;arbre2(60,5)`
On obtient :

### 7.2.2 Un arbre a p branches

Un arbre est composé d’un tronc de hauteur h et de p branches également réparties et que l’on définit comme étant chacune un arbre de tronc h/2.
On tape dans un éditeur de programmes :

    //tourne_gauche;arbre3(80,4)
    arbre3(h,p):={
    si (h<5) alors
    avance(h);
    recule(h);
    sinon
    avance(h);
    tourne_droite(90*(p-1)/p);
    repete(p,arbre3(h/2,p),tourne_gauche(180/p));
    tourne_droite(90*(p+1)/p);
    recule(h);
    fsi;
    }:;

On valide avec `OK` ou avec `F9`.
On tape par exemple dans une ligne de commande :
`efface;tourne_gauche;arbre3(80,4)`
On obtient :
Ou bien, on rajoute un paramètre n (la profondeur) pour faire le test d’arrêt, on tape dans un éditeur de programmes :

    //tourne_gauche;arbre4(60,5,3)
    arbre4(h,p,n):={
    si (n==0) alors
    avance(h);
    recule(h);
    sinon
    avance(h);
    tourne_droite(90*(p-1)/p);
    repete(p,arbre4(h/2,p,n-1),tourne_gauche(180/p));
    tourne_droite(90*(p+1)/p);
    recule(h);
    fsi;
    }:;

On valide avec `OK` ou avec `F9`.
On tape par exemple dans une ligne de commande :
`efface;tourne_gauche;arbre4(80,5,4)`
On obtient :

Et maintenant, un arbre aléatoire :
à chaque nœud on choisit, de façon aléatoire le rapport k de réduction, qui fera les p branches comme un arbre réduit avec le coefficient k.
On tape dans un éditeur de programmes :

    //tourne_gauche ;saute(-80);arbre5(60,4,3);
    arbre5(h,p,n):={
    local k;
    si (n==0) alors
    avance(h);
    recule(h);
    sinon
    avance(h);
    tourne_droite(90*(p-1)/p);
    k:=hasard(0,1);
    repete(p,arbre5(h*k,p,n-1),tourne_gauche(180/p));
    tourne_droite(90*(p+1)/p);
    recule(h);
    fsi;
    }:;

On valide avec `OK` ou avec `F9`.
On tape par exemple dans une ligne de commande :
`efface;tourne_gauche;arbre5(60,5,4)`
On obtient :

Et enfin, un arbre encore plus aléatoire :
pour chaque branche on choisit, de façon aléatoire le rapport `hasard(0,1)` de réduction, qui fera cette branche comme un arbre réduit avec ce coefficient.
On tape dans un éditeur de programmes :

    //tourne_gauche ;saute(-80);arbre6(60,4,3);
    arbre6(h,p,n):={
    si (n==0) alors
    avance(h);
    recule(h);
    sinon
    avance(h);
    tourne_droite(90*(p-1)/p);
    repete(p,arbre6(h*hasard(0,1),p,n-1),tourne_gauche(180/p));
    tourne_droite(90*(p+1)/p);
    recule(h);
    fsi;
    }:;

On valide avec `OK` ou avec `F9`.
On tape par exemple dans une ligne de commande :
`efface;tourne_gauche;arbre6(60,5,4)`
On obtient :

### 7.2.3 Un arbre ramifié

Ici on suppose que, du tronc de longueur h, il part p branches de longueur h/2. Ces branches donnent naissance à p−1 branches de longueur h/4 etc... jusqu’à p=2. On tape dans un éditeur de programmes :

    //tourne_gauche;saute(-80);arbre7(60,5)
    arbre7(h,p):={
    avance(h);
    si (p>=2) alors
    tourne_droite(90*(p-1)/p);
    repete(p,arbre7(h/2,p-1),tourne_gauche(180/p));
    tourne_droite(90*(p+1)/p);
    fsi;
    recule(h);
    }:;

On valide avec `OK` ou avec `F9`.
On tape par exemple dans une ligne de commande :
`efface;tourne_gauche;arbre7(80,5)`
On obtient :

En utilisant aussi la profondeur dans le test d’arrêt on tape dans un éditeur de programmes :

    //tourne_gauche;saute(-80);arbre8(90,5,3)
    arbre8(h,p,n):={
    avance(h);
    si (p>=2 et n>=1) alors
    tourne_droite(90*(p-1)/p);
    repete(p,arbre8(h/2,p-1,n-1),tourne_gauche(180/p));
    tourne_droite(90*(p+1)/p);
    fsi;
    recule(h);
    }:;

On valide avec `OK` ou avec `F9`.
On tape par exemple dans une ligne de commande :
`efface;tourne_gauche;arbre8(80,6,5)`
On obtient :
Exercice Refaire les exemples précédents mais en ne dessinant que la frondaison de l’arbre, c’est à dire l’arbre sans son tronc.
Une réponse Voici la réponse correspondant à `arbre7` et à `arbre8`. Bien sûr, pour avoir la frondaison de `arbre7(60,5)` il faut taper `arbre9(30,5)` et pour avoir la frondaison de `arbre8(60,5,3)` il faut taper `arbre10(30,5,3)`.

    //tourne_gauche;saute(-80);arbre9(90,5,3)
    arbre9(h,p):={
    si (p>=2) alors
    tourne_droite(90*(p-1)/p);
    repete(p,avance(h),arbre9(h/2,p-1),recule(h),tourne_gauche(180/p));
    tourne_droite(90*(p+1)/p);
    fsi;
    }

    //tourne_gauche;saute(-80);arbre10(90,5,3)
    arbre10(h,p,n):={
    si (n>=1 et p>=2) alors
    tourne_droite(90*(p-1)/p);
    repete(p,avance(h),arbre10(h/2,p-1,n-1),recule(h),tourne_gauche(180/p));
    tourne_droite(90*(p+1)/p);
    fsi;
    }

### 7.2.4 Un sapin

Pour décrire un sapin, il faut choisir un paramètre par exemple sa hauteur h du sapin.
On dit alors qu’un sapin de hauteur h est composé de :

- deux branches basses latérales symétriques de longueur h/2 et faisant un angle de 60 degrés avec le tronc,
- d’un bout de tronc de hauteur h/4,
- d’une tête de hauteur 3h/4h .

Cette définition sera récursive si on dit que les deux branches basses latérales sont des sapins plus petits (de hauteur égale à la moitié de la hauteur du sapin) et que la tête est aussi un sapin plus petit (de hauteur égale au trois-quart de la hauteur du sapin). Le tronc a donc pour hauteur le quart de la hauteur du sapin. Il nous faut alors définir ce que l’on considére comme sapin "initial" : c’est le sapin formé d’un tronc unique.
Voici la croissance de ces sapins :
On tape dans un éditeur de programme :

    //tourne_gauche;sapin1(90)
    sapin1(h):={
    si (h<5) alors
    avance(h);
    recule(h);
    sinon
    tourne_droite(60);
    sapin1(h/2);
    tourne_gauche(120);
    sapin1(h/2):
    tourne_droite(60);
    avance(h/4);
    sapin1(3*h/4);
    recule(h/4);
    fsi;
    }:;

Ou on tape en utilisant pour faire le test d’arrêt la profondeur n :

    //tourne_gauche;sapin2(90,4)
    sapin2(h,n):={
    si (n==0) alors
    avance(h);
    recule(h);
    sinon
    tourne_droite(60);
    sapin2(h/2,n-1);
    tourne_gauche(120);
    sapin2(h/2,n-1):
    tourne_droite(60);
    avance(h/4);
    sapin2(3*h/4,n-1);
    recule(h/4);
    fsi;
    }:;

On valide avec `OK` ou avec `F9`.
On tape par exemple dans une ligne de commande :
`efface;tourne_gauche;sapin2(100,7)`
On obtient :
Les différentes étapes ont été obtenus en exécutant :
`tourne_gauche; sapin2(90,0)` puis
`tourne_gauche; sapin2(90,1)` puis
`tourne_gauche; sapin2(90,2)` puis
`tourne_gauche; sapin2(90,3)`.

## 7.3 Les flocons de Koch

Voici les étapes de construction d’une courbe découverte par Koch :

On voit l’étape 0 : un segment de longueur l.
Pour obtenir l’étape 1, on divise ce segment de longueur l en trois et on réalise la deuxième figure qui est composée de quatre segments de longueur l/3 (le deuxiéme et troisiéme segments sont les côtés d’un triangle équilatéral), puis on recommence en transformant chacun de ces 4 segments en 4 segments....
et cela tant que l ≥ 10. On tape dans un éditeur de programme :

    //koch1(90)
    koch1(l):={
    si (l<10) alors
    avance(l);
    sinon
    koch1(l/3);tourne_gauche(60);
    koch1(l/3);tourne_droite(120);
    koch1(l/3);tourne_gauche(60);
    koch1(l/3);
    fsi;
    }:;

Ou on tape en utilisant un paramètre n représentant la profondeur (i.e. le nombre d’appels récursifs) :

    //koch2(90,3)
    koch2(l,n):={
    si (n==0) alors
    avance(l);
    sinon
    koch2(l/3,n-1);tourne_gauche(60);
    koch2(l/3,n-1);tourne_droite(120);
    koch2(l/3,n-1);tourne_gauche(60);
    koch2(l/3,n-1);
    fsi;
    }:;

On valide avec `OK` ou avec `F9`.
On tape par exemple dans une ligne de commande :
`efface;koch2(270,7)`
On obtient :
Les dessins des différentes étapes ont été obtenus en tapant :
`koch2(90,0)` puis,
`koch2(90,1)` puis,
`koch2(90,2)`

## 7.4 Les courbes de Péano

Parmi les nombreuses courbes inventées par Péano, prouvant l’existence de courbes remplissant un carré, on n’en retiendra que trois, celles décrites dans les paragraphes suivants.

### 7.4.1 La courbe C0 de Péano

Soit un carré de diagonale l :
au jour 0, on trace une diagonale,
au jour 1, on divise ce carré en 9 carrés et on trace les diagonales de ces carrés, de façon à avoir un trait continu en parcourant la première ligne, puis la deuxième, et enfin la troisième, comme ci-dessous :
puis on recommence le même processus.
On tape dans un éditeur de programme :

    //peano(90)
    peano(l):={
      si (l<10) alors avance(l);
      sinon
      peano(l/3);
      tourne_droite;peano(l/3);
      tourne_gauche;peano(l/3);
      tourne_gauche;peano(l/3);
      tourne_gauche;peano(l/3);
      tourne_droite;peano(l/3);
      tourne_droite;peano(l/3);
      tourne_droite;peano(l/3);
      tourne_gauche;peano(l/3);
      fsi
    }:;

On valide avec `OK` ou avec `F9`.
On tape par exemple dans une ligne de commande :
`efface;tourne_gauche 45;peano(200)`
On obtient :

### 7.4.2 La courbe de Péano binaire

Soit un carré de coté l :
au jour 0, on trace un segment de longueur l i.e. un coté du carré,
au jour 1, on remplace ce segment, en traçant 4 segments de longueur l/2 qui sont disposés selon les trois cotés d’un rectangle situé à gauche de la position de la tortue, de largeur l/2 et de longueur l,
au jour 2, on remplace chaque segment de longueur k par 4 segments de longueur k/2 en tracant les trois coés d’un rectangle de largeur k/2 et de longueur k et situé soit à droite soit à gauche de la position de la tortue comme cela :
puis on recommence le même processus.
On remarque que l’on remplace un segment en tracant un rectangle situé soit à droite soit à gauche de la position de la tortue : on introduit donc un paramètre s qui vaut 1 si ce rectangle se situe à droite et qui vaut -1 si ce rectangle se situe à gauche.
On tape :

    //peanob(90,1)
    peanob(l,s):={
      si (l<10) alors avance(l);
      sinon
      tourne_gauche(-90*s);peanob(l/2,-s);
      tourne_droite(-90*s);peanob(l/2,s);
      peanob(l/2,s);tourne_droite(-90*s);
      peanob(l/2,-s);tourne_gauche(-90*s);
      fsi
    }:;

On valide avec `OK` ou avec `F9`.
On tape par exemple dans une ligne de commande :
`efface;peanob(200,-1)`
On obtient :

### 7.4.3 La courbe de Péano ternaire

Au jour 1, on trace la première courbe `peano1(l,0)` dans le carré de coté l,
Au jour 2, on trace la deuxème courbe dans le carré de coté l obtenue en partageant le carré en 9 carrés et en traçant dans le premier carré `peano1(l,0)`, et dans les autres soit `peano1(l,1)`, soit `peano1(l,-1)`, de façon à ce que les courbes se raccordent entre elles.
Voici les dessins, où la position de départ et d’arrivée de la tortue est choisie comme indiquée sur la première figure :
`peano1(60,0)` `peano1(60,1)` `peano1(60,-1)` On décide alors de prendre comme départ de la tortue le sommet inférieur gauche du carré. On définit `car(l)` qui dessine un carré de côté `l`, on tape :

    //carre de cote l
    car(l):={
    repete(4,avance(l),tourne_gauche 90);
    }:;
    //peano1(30,0) ou peano1(30,1) ou peano1(30,-1)
    peano1(l,s):={
    si (s==-1) alors
      tourne_droite(45);saute(-l*sqrt(2)/6);rond(round(l*sqrt(2)/6.),90);
    sinon
      si (s==1) alors
       tourne_gauche(135);saute(-l*sqrt(2)/6);rond(round(-l*sqrt(2)/6.),90);
      sinon
       tourne_gauche(45);
       saute(l*sqrt(2)/6);
      fsi;
    fsi;
    rond(round(l*sqrt(2)/6.),90);
    rond(round(-l*sqrt(2)/6.),270);
    rond(round(l*sqrt(2)/6.),270);
    rond(round(-l*sqrt(2)/6.),90);
    saute(l*sqrt(2)/6);
    tourne_droite(45);
    }:;
    //peanot(90,0)
    peanot(l,s):={
      si (l<31) alors
        peano1(l,s);
      sinon
        peanot(l/3,s);
        tourne_droite;peanot(l/3,1);
        tourne_gauche;peanot(l/3,-1);
        tourne_gauche;peanot(l/3,-1);
        tourne_gauche;peanot(l/3,-1);
        tourne_droite;peanot(l/3,1);
        tourne_droite;peanot(l/3,1);
        tourne_droite;peanot(l/3,1);
        tourne_gauche;peanot(l/3,-1);
      fsi;
    }:;

On valide avec `OK` ou avec `F9`.
On tape par exemple dans une ligne de commande :

    dessine_tortue;
    crayon jaune;
    car(90);
    crayon noir;
    peanot(90,0);

On obtient :

Mais, on voit qu’à cause des erreurs d’arrondis, la courbe n’est pas centrée dans le carré. En particuler, `peanot(120,0), peanot(110,0),peanot(100,0)` donne le même dessin !!!

On décide alors de prendre comme départ de la tortue le centre du carré.

    carc(l):={
    pas_de_cote -l/2;
    repete(4,avance l/2,tourne_gauche ,avance l/2);
    pas_de_cote l/2;
    }:;
    pean1(l,s):={
    tourne_gauche 45;
    rond(round(l*sqrt(2)/6.),270);
    rond(round(-l*sqrt(2)/6.),90);
    si (s==-1) alors
      rond(round(-l*sqrt(2)/6.),90);
      tourne_droite 180;
      rond(round(l*sqrt(2)/6.),90);
    sinon
      si (s==1) alors
       rond(round(l*sqrt(2)/6.),90);
       tourne_droite 180;
       rond(round(-l*sqrt(2)/6.),90);
       sinon tourne_droite 180;
      fsi;
    fsi;
    rond(round(l*sqrt(2)/6.),90);
    rond(round(-l*sqrt(2)/6.),270);
    tourne_droite 225;
    }:;
    pean2(l,s):={
    tourne_droite 135;
    rond(round(l*sqrt(2)/6.),270);
    rond(round(-l*sqrt(2)/6.),90);
    tourne_droite 180;
    rond(round(l*sqrt(2)/6.),90);
    rond(round(-l*sqrt(2)/6.),270);
    tourne_gauche -45;
    }:;
    pean(l,s):={
    pean2(l,s);
    pean1(l,s)
    }:;
    peant(l,s):={
      si (l<31) alors
        pean(l,s);
      sinon
      pas_de_cote -l/3;
      saute -l/3;
      peant(l/3,s);
      saute l/3;tourne_droite;peant(l/3,1);
      pas_de_cote l/3;tourne_gauche;peant(l/3,-1);
      pas_de_cote l/3;tourne_gauche;peant(l/3,-1);
      pas_de_cote l/3;tourne_gauche;peant(l/3,-1);
      saute l/3;tourne_droite;peant(l/3,1);
      saute l/3;tourne_droite;peant(l/3,1);
      saute l/3;tourne_droite;peant(l/3,1);
      pas_de_cote l/3;tourne_gauche;peant(l/3,-1);
      pas_de_cote -l/3;saute -l/3;
    fsi;
    }:;

On valide avec `OK` ou avec `F9`.
On tape par exemple dans une ligne de commande :

    dessine_tortue;
    peant(180,0);
    crayon jaune;
    carc(180);

On obtient :
Mais ce n’est pas encore parfait, la courbe est bien centrée dans le carré mais les raccords entres les différents morceaux ne se fait pas bien : c’est toujours à cause des erreus d’arrondis !

On peut aussi supprimer les `saute`, les `tourne` et les √2, c’est à dire en prenant comme départ et d’arrivée de la tortue les tangentes aux arcs et comme paramètre l la diagonale du carré et en rajoutant le paramètre n pour la profondeur.
On tape :

    //fait le dessin de la tortue
    des_tor():={
    cache_tortue;
    tourne_gauche;
    avance 5;
    tourne_droite(180-180/pi*atan(3.4));
    avance(sqrt(25+17^2));
    tourne_droite(180-2*180/pi*atan(1/3.4));
    avance(sqrt(25+17^2));
    tourne_droite(180-180/pi*atan(3.4));
    avance 5;tourne_droite;
    montre_tortue;
    }:;
    //carre de cote l
    card(d):={
    repete(4,avance(d/sqrt(2)),tourne_gauche 90);
    }:;
    //peano2(30,0) ou peano2(30,-1) ou peano2(30,1)
    peano2(l,s):={
      si (s==-1) alors
       rond(round(l/6),90);
      sinon
        si (s==1) alors
        rond(round(-l/6),90);
        fsi;
      fsi;
      rond(round(l/6),90);
      rond(round(-l/6),270);
      rond(round(l/6),270);
      rond(round(-l/6),90);
    }:;

    //tourne_gauche 45;peanot2(90,0,2)
    peanot2(l,s,n):={
      si (n==1) alors
        peano2(l,s);
      sinon
        peanot2(l/3,s,n-1);
        peanot2(l/3,1,n-1);
        peanot2(l/3,-1,n-1);
        peanot2(l/3,-1,n-1);
        peanot2(l/3,-1,n-1);
        peanot2(l/3,1,n-1);
        peanot2(l/3,1,n-1);
        peanot2(l/3,1,n-1);
        peanot2(l/3,-1,n-1);
     fsi;
    }:;

On remarquera que `peanot2` commence à un sommet du carré et se termine en un point proche du sommet opposé : le point d’arrivée est ici fonction de la valeur du paramètre `n` et est a une distance de l/3n/2 du sommet opposé au carré.
Puis on tape par exemple :

    efface ;
    tourne_gauche 45;
    crayon jaune;
    dessine_tortue;
    crayon noir;
    peanot2(180,0,2);
    des_tor();
    saute 180/3^2/2;
    tourne_droite 135;
    crayon jaune;
    card(180);
    cache_tortue;

On obtient :
Puis on tape par exemple :

    efface ;
    tourne_gauche 45;
    crayon jaune;
    dessine_tortue;
    crayon noir;
    peanot2(162,0,4);
    des_tor();
    saute 162/3^4/2;
    tourne_droite 135;
    crayon jaune;
    card(162);
    cache_tortue;

On obtient :
Si on définit :

    //peanot1(90,0,2)
    peanot1(l,s,n):={
    tourne_gauche 45;
    saute(l/2/3^n);
    peanot2(l,s,n);
    saute(l/2/3^n);
    tourne_droite 45;
    }:;

On a :
`peanot1(l/sqrt(2),s,n)` ressemble à `peanot(l,s)`....mais ce n’est pas parfait à cause des erreurs d’arrondis.

## 7.5 La courbe de Hilbert

C’est une courbe remplissant un carré qui a été découverte par Hilbert : cette courbe se fait a partir de quatre procédures récursives qui s’appellent les unes les autres et que j’ai appelé `hilbg`, `hilbd`, `bertg`, `bertd`.
Voici les étapes de construction : - au jour 0 on trace un segment,
- au jour 1 on trace les dessins où on a dessiné les positions de départ et d’arrivée de la tortue (la forme pleine représente la tortue au départ et la forme vide celle d’arrivée).
`hilbg` `hilbd` `bertg` `bertd`
`hilbg` est composée de 4 segments qui sont le dessin obtenu au jour 0 par `hilbd` `hilbg` `bertg` `bertd`
`hilbd` est composée de 4 segments qui sont le dessin obtenu au jour 0 par `hilbg` `hilbd` `bertd` `bertg`
`bertg` est composée de 4 segments qui sont le dessin obtenu au jour 0 par `hilbd` `hilbg` `bertg` `hilbd`
`bertd` est composée de 4 segments qui sont le dessin obtenu au jour 0 par `hilbg` `hilbd` `bertd` `hilbg`
On écrit :

    //hilbg(200)
    hilbg(l):={
    si (l<=10) alors
    avance(l);
    sinon
    tourne_gauche(90);hilbd(l/2);
    tourne_droite(90);hilbg(l/2);
    tourne_droite(90);bertg(l/2);
    tourne_gauche(90);bertd(l/2);
    fsi;
    }:;
    hilbd(l):={
    si (l<=10) alors
    avance(l);
    sinon
    tourne_droite(90);;hilbg(l/2);
    tourne_gauche(90);;hilbd(l/2);
    tourne_gauche(90);bertd(l/2);
    tourne_droite(90);bertg(l/2);
    fsi;
    }:;
    bertg(l):={
    si (l<=10) alors
    avance(l);
    sinon
    tourne_droite(180);hilbd(l/2);
    tourne_droite(90);hilbg(l/2);
    tourne_droite(90);bertg(l/2);
    hilbd(l/2);
    fsi;
    }:;
    bertd(l):={
    si (l<=10) alors
    avance(l);
    sinon
    tourne_droite(180);hilbg(l/2);
    tourne_gauche(90);hilbd(l/2);
    tourne_gauche(90);bertd(l/2);
    hilbg(l/2);
    fsi;
    }:;

On tape par exemple :

    efface ;
    crayon jaune;
    dessine_tortue;
    crayon noir;
    hilbg(200);

On obtient :

## 7.6 Le dragon

0/ Prener une longue bande de papier AB de longueur l : c’est le dragon au jour 0.
1/ Plier cette bande de papier en deux, en amenant B en coincidence avec A par une rotation d’angle +2 et de centre C, milieu de AB : en dépliant à angle droit, on a le dragon au jour 1.
2/ Replier comme précédemment, puis plier à nouveau en deux, en amenant C en coincidence avec A par une rotation d’angle +2 : en dépliant à angle droit chaque pliure, on a le dragon au jour 2.
3/ Recommencer tant que la longueur à plier n’est pas trop petite (pour la tortue on s’arrête de plier si l<10).
Voici les 5 premières étapes :
On remarque que le segment AC et le segment CB donne naissance à deux dragons symétriques : on appelle `dragong` le dragon obtenu par des pliages fait avec une rotation d’angle +2 et `dragond` le dragon obtenu par des pliages fait avec une rotation d’angle −2.
On tape :

    //dragong(1800)
    dragong(l):={
    si (l<10) alors
    avance(l);
    sinon
    dragong(l/2);
    tourne_gauche(90);
    dragond(l/2);
    fsi;
    }:;
    dragond(l):={
    si (l<10) alors
    avance(l);
    sinon
    dragong(l/2);
    tourne_droite(90);
    dragond(l/2);
    fsi;
    }:;

Ou encore en utilisant une seule procédure `dragon2` mais avec un paramètre supplémentaire `s` (si `s=1` on a un dragon gauche et si `s=-1` on a un dragon droit).
On tape :

    //dragon2(1800,1)
    dragon2(l,s):={
    si (l<10) alors
    avance(l);
    sinon
    dragon2(l/2,1);
    tourne_gauche(90*s);
    dragon2(l/2,-1);
    fsi;
    }

On tape par exemple :

    efface;
    rayon jaune;
    dessine_tortue;
    crayon noir;
    dragon2(2880,1)}

Ou encore on écrit `dragon3` en utilisant le paramètre n profondeur pour faire le test d’arrêt :

    //dragon3(1800,1,3)
    dragon3(l,s,n):={
    si (n==0) alors
    avance(l);
    sinon
    dragon3(l/2,1,n-1);
    tourne_gauche(90*s);
    dragon3(l/2,-1,n-1);
    fsi;
    }:;

Les dessins des 5 premières étapes ont été réalisés en exécutant :

    efface ;
    crayon jaune;
    dessine_tortue;
    crayon noir;
    dragon3(60,1,0);
    des_tor();
    saute 20;
    crayon jaune;
    dessine_tortue;
    crayon noir;
    dragon3(60,1,1);
    des_tor();
    pas_de_cote -20;
    saute -30;
    tourne_droite ;
    crayon jaune;
    dessine_tortue;
    crayon noir;
    dragon3(60,1,2);
    des_tor();
    pas_de_cote -40;
    saute -30;
    tourne_droite ;
    crayon jaune;
    dessine_tortue;
    crayon noir;
    dragon3(60,1,3);des_tor();
    pas_de_cote -60;
    saute -15;
    tourne_droite ;
    crayon jaune;
    dessine_tortue;
    crayon noir;
    dragon3(60,1,4);

### 7.6.1 La courbe de Gosper

Voici `gosperg(40,1);` et `gosperd(40,1);` qui forment la courbe de Gosper et l’étape 2 (`gosperg(40,2)`) :
On remarque que les 7 segments de la première courbe donne naissance soit à la première courbe, soit à la courbe obtenue en faisant le trajet en sens inverse. On va donc définir deux procédures :
`gosperg` et `gosperd` qui réalisent les dessins suivants (avec comme position de départ de la tortue, le triangle plein et comme position d’arrivée, le triangle vide) :

On déduit l’écriture de `gosperd` de celle de `gosperg` en mettant les instructions de `gosperg` de la dernière à la première en changeant `gauche` en `droite` et réciproqement.

    //gosperg(80,3)
    gosperg(l,n):={
      si (n==0) alors avance(l);
    sinon
      gosperg(l/2,n-1);
      tourne_gauche(60);
      gosperd(l/2,n-1);
      tourne_gauche(120);
      gosperd(l/2,n-1);
      tourne_droite(60);
      gosperg(l/2,n-1);
      tourne_droite(120);
      gosperg(l/2,n-1);
      gosperg(l/2,n-1);
      tourne_droite(60);
      gosperd(l/2,n-1);
      tourne_gauche(60);
    fsi;
    };
    gosperd(l,n):={
      si (n==0) alors avance(l);
    sinon
      tourne_droite(60);
      gosperg(l/2,n-1);
      tourne_gauche(60);
      gosperd(l/2,n-1);
      gosperd(l/2,n-1);
      tourne_gauche(120);
      gosperd(l/2,n-1);
      tourne_gauche(60);
      gosperg(l/2,n-1);
      tourne_droite(120);
      gosperg(l/2,n-1);
      tourne_droite(60);
      gosperd(l/2,n-1);
    fsi;
    };

On tape : `gosperg(80,3)`
On obtient :
`la courbe de gosper à la troisième génération`
Autre écriture on choisit les flèches départ et d’arrivée comme ci-dessous mais alors la tortue a changé de direction il faut donc aussi la faire changer de la même direction dans le test d’arrêt. L’écriture de `gosperd` se fait encore à partir de celle de `gosperg`, en mettant les instructions de `gosperg` de la dernière à la première en changeant `gauche` en `droite` et réciproqement, et cela même dans le test d’arrêt!!!

    //gosperg2(80,3)
    gosperg2(l,n):={
     si (n==0) alors
       avance(l);tourne_droite(60);
     sinon
      gosperg2(l/2,n-1);
      tourne_gauche(60);
      gosperd2(l/2,n-1);
      tourne_gauche(60);
      gosperd2(l/2,n-1);
      tourne_droite(60);
      gosperg2(l/2,n-1);
      tourne_droite(60);
      gosperg2(l/2,n-1);
      tourne_gauche(60);
      gosperg2(l/2,n-1);
      tourne_droite(60);
      gosperd2(l/2,n-1);
     fsi;
    }:;
    gosperd2(l,n):={
     si (n==0) alors
      tourne_gauche(60);avance(l);
     sinon
      gosperg2(l/2,n-1);
      tourne_gauche(60);
      gosperd2(l/2,n-1);
      tourne_droite(60);
      gosperd2(l/2,n-1);
      tourne_gauche(60);
      gosperd2(l/2,n-1);
      tourne_gauche(60);
      gosperg2(l/2,n-1);
      tourne_droite(60);
      gosperg2(l/2,n-1);
      tourne_droite(60);
      gosperd2(l/2,n-1);
     fsi;
    }:;

On tape :
`gosperg2(80,3)`
On obtient :
`la courbe de gosper à la troisième génération`