<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>http://os-vps418.infomaniak.ch:1250/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Laurent+corantin</id>
	<title>Wiki du LAMA (UMR 5127) - Contributions [fr]</title>
	<link rel="self" type="application/atom+xml" href="http://os-vps418.infomaniak.ch:1250/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Laurent+corantin"/>
	<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php/Sp%C3%A9cial:Contributions/Laurent_corantin"/>
	<updated>2026-05-21T05:35:23Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.39.4</generator>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=INFO401_corr_TD_TP&amp;diff=4173</id>
		<title>INFO401 corr TD TP</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=INFO401_corr_TD_TP&amp;diff=4173"/>
		<updated>2009-05-27T16:22:50Z</updated>

		<summary type="html">&lt;p&gt;Laurent corantin : /* Le TP2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Préliminaires==&lt;br /&gt;
&lt;br /&gt;
Pour afficher correctement dans le wiki, allez voir un peu comment on fait. Vous pouvez regarder par exemple sur le [[INFO401 | wiki du cours]] ou directement sur des articles de [http://fr.wikipedia.org/wiki/Accueil Wikipedia]. La documentation de mediawiki se trouve [http://meta.wikimedia.org/wiki/Aide:Éditeur ici].&lt;br /&gt;
&lt;br /&gt;
Un truc important : pour rentrer du code Caml, il faut mettre les balises &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;...&amp;lt;/source&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; autour de votre code. Allez par exemple voir le début de la section sur [[#Le TD1 et le TP0 | le TD1 et TP0]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vous pouvez aller discuter des corrections dans les sujets de discussions associes...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD1 et le TP0==&lt;br /&gt;
&lt;br /&gt;
Pour vous montrer un exemple de ce que j&#039;attends, voila la correction de la fonction factorielle. (C&#039;était facile...) J&#039;ai volontairement mis beaucoup de commentaires...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;La fonction factorielle (TD1, exercice 2, question 2)&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but est de calculer la fonction &amp;lt;math&amp;gt;!n = 1\times2\times \cdots \times n&amp;lt;/math&amp;gt; par récurrence. La version typée est verbeuse de la fonction correspondante en Caml donne :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* fonction factorielle : c&#039;est la factorielle habituelle des mathématiciens... *)&lt;br /&gt;
let rec fact (n:int) : int =&lt;br /&gt;
  if (n&amp;gt;1)&lt;br /&gt;
  then  n * (fact (n-1))&lt;br /&gt;
  else 1      (* rq : pour que le programme ne boucle pas sur les valeurs négatives, on renvoie 1 dés que n&amp;lt;1 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme la fonction est récursive, il ne faut pas oublier le &amp;lt;tt&amp;gt;rec&amp;lt;/tt&amp;gt; au début de la définition.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On aurait pu faire une autre version, qui fonctionne différemment sur les nombres négatifs :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fact&#039; = function&lt;br /&gt;
   n when (n&amp;gt;0) -&amp;gt; n * fact&#039; (n-1)&lt;br /&gt;
 | n when (n&amp;lt;0) -&amp;gt; n * fact&#039; (n+1)&lt;br /&gt;
 | _ -&amp;gt; 1  (* si n n&#039;est ni plus petit que 0 ni plus grand que 0, n est égal à 0, et on renvoie donc 1 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;ai volontairement mis une version qui contient plusieurs choses que nous n&#039;avons pas encore vues en cours :&lt;br /&gt;
* utilisation de &amp;quot;&amp;lt;tt&amp;gt;function&amp;lt;/tt&amp;gt;&amp;quot; plutôt que &amp;lt;tt&amp;gt;fun&amp;lt;/tt&amp;gt;,&lt;br /&gt;
* le symbole &amp;quot;&amp;lt;tt&amp;gt;|&amp;lt;/tt&amp;gt;&amp;quot;,&lt;br /&gt;
* le mot clé &amp;quot;&amp;lt;tt&amp;gt;when&amp;lt;/tt&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Vous devriez pouvoir comprendre ce que fait la fonction. Sinon, voici une version que vous auriez pu écrire :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fact_bis = fun n -&amp;gt;&lt;br /&gt;
  if (n=0)&lt;br /&gt;
  then 1&lt;br /&gt;
  else begin&lt;br /&gt;
    if (n&amp;gt;0)&lt;br /&gt;
    then n*fact_bis (n-1)&lt;br /&gt;
    else n*fact_bis (n+1)   (* dans ce cas, n est forcement négatif *)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Les fonctions sommes &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il s&#039;agit ici d&#039;écrire la fonction qui va additionner les carrés des entiers de 1 jusqu&#039;à un nombre donné.&lt;br /&gt;
&lt;br /&gt;
Cela donne :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_carre b =&lt;br /&gt;
if (b=0) then 0&lt;br /&gt;
else (b*b) + somme_carre (b-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite on nous demande de calculer la somme des cubes des entiers de 1 jusqu&#039;à un nombre donné. On pourrait faire le même programme en remplaçant b*b par b*b*b, mais on va définir une fonction puissance (car elle n&#039;existe pas d&#039;origine sous Caml), qui nous servira aussi pour la suite... :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec puissance x a =&lt;br /&gt;
if (a = 0) then 1&lt;br /&gt;
else x * puissance x (a-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On doit maintenant calculer la somme des &amp;lt;math&amp;gt;i^i&amp;lt;/math&amp;gt;, i variant de 1 à un nombre donné :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_puissance b =&lt;br /&gt;
if (b=0) then 0&lt;br /&gt;
else (puissance b b) + somme_puissance (b-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut définir une unique fonction qui permettrait de faire toutes ces sommes, celle-ci aura pour argument une fonction quelconque :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_fonction n f = (* f étant une fonction *)&lt;br /&gt;
if (n=0) then f 0&lt;br /&gt;
else f n + somme_fonction (n-1) f;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
cette fonction est de type &amp;quot;&amp;lt;tt&amp;gt;int -&amp;gt; fun -&amp;gt; int&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Nombres pairs et impairs (TP0 Partie 2 Question 2) &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut écrire les fonctions récursives pairs et impairs, qui renvoient vrai si le nombre est pair (respectivement impair) et faux si le nombre est impair (respectivement pair);&lt;br /&gt;
Ici nous devons déclarer simultanément les deux fonctions, car chacune fait appel à l&#039;autre lors de son exécution.&lt;br /&gt;
&lt;br /&gt;
Cela donne :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec pair n =&lt;br /&gt;
  if (n=0) then true&lt;br /&gt;
  else impair (n-1)&lt;br /&gt;
and impair n =&lt;br /&gt;
  if (n=0) then false&lt;br /&gt;
  else  pair (n-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Suite de Fibonacci &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La suite de fibonacci est tel que u&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;=0 u&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;=1 et u&amp;lt;sub&amp;gt;n+2&amp;lt;/sub&amp;gt;=u&amp;lt;sub&amp;gt;n+1&amp;lt;/sub&amp;gt;+u&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib n =&lt;br /&gt;
if (n=0) then 0&lt;br /&gt;
else if (n=1) then 1&lt;br /&gt;
else fib (n-1) + fib (n-2);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La plus grande valeur que l&#039;on peut obtenir sans que cela soit trop long est 24157817, ce qui correspond à fib 37.&lt;br /&gt;
Nous trouvons qu&#039;il faut déjà 88 additions pour calculer fib 10.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Rq :&#039;&#039;&#039; fib de 37 prend effectivement beaucoup de temps. Il faut 39088168 additions avant d&#039;en arriver à bout. Il est possible de faire une version de Fibonacci qui va très vite et qui calcule &amp;lt;tt&amp;gt;fib 37&amp;lt;/tt&amp;gt; en seulement 36 additions...&lt;br /&gt;
: Comment ?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Dragon ! &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;i&amp;gt; Le dragon est une créature mythique, présente dans de nombreuses cultures.&lt;br /&gt;
  On peut déterminer deux grands types de dragons : le dragon occidental et le dragon oriental&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction dragon a pour but de dessiner un dragon, pour cela on utilise une fonction récursive qui admet pour argument le nombre n d&#039;itération de la fonction, et les coordonnées de 2 points. A chaque itération, la fonction calcule pour chaque segment, un nouveau point et le relie ensuite aux deux autres.&lt;br /&gt;
&lt;br /&gt;
On obtient en tout 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; segments entremêlés, qui forment un dragon.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s go !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec dragon (n:int) (a:int) (b:int) (c:int) (d:int) : unit =&lt;br /&gt;
if (n = 0) then (moveto a b ; lineto c d)&lt;br /&gt;
               else begin&lt;br /&gt;
                      let x = (a+c+d-b)/2 in&lt;br /&gt;
                      let y = (b+d+a-c)/2 in&lt;br /&gt;
                      dragon (n-1) a b x y ;&lt;br /&gt;
                      dragon (n-1) c d x y&lt;br /&gt;
                    end ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Rq : &#039;&#039;&#039; votre version du dragon est bien, mais pas très précises. (Je chipote un peu...)  Pour les paramètres (&amp;lt;tt&amp;gt;dragon 11 100 100 400 400&amp;lt;/tt&amp;gt;), de nombreux carrés ne sont pas bien tracés.&lt;br /&gt;
:Comment expliquez-vous cela, et comment pouvez-vous le corriger ?&lt;br /&gt;
&lt;br /&gt;
::Pour améliorer la précision je suggère de passer les coordonnées en type Float. --[[Utilisateur:Nicolas|Nicolas]] 31 janvier 2009 à 11:42 (CET)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD2==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exercice 1 : Tuples&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 4 :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
On définit la fonction curry par:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let curry (f: &#039;a * &#039;b -&amp;gt; &#039;c) : &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;c&lt;br /&gt;
     = fun x y -&amp;gt; f(x,y);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ou encore en simplifiant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let curry f x y = f(x,y);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On définit ensuite la fonction uncurry par:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry (f: &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;c) : &#039;a * &#039;b -&amp;gt; &#039;c&lt;br /&gt;
     = fun x -&amp;gt; f (fst x) (snd x);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ou encore de trois autres manières plus simplifiées:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = fun x -&amp;gt; f (fst x) (snd x);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = fun x -&amp;gt; match x with (a,b) -&amp;gt; f a b;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = function (a,b) -&amp;gt; f a b;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Avantage de la première forme (à plusieurs arguments): Elle permet une application partielle: on peut appliquer cette fonction à une seule partie des arguments.&lt;br /&gt;
&lt;br /&gt;
Inconvénients de la seconde forme (à un argument): &lt;br /&gt;
*il faut faire appel à fst, snd;&lt;br /&gt;
*Caml doit séparer les paires: c&#039;est une perte de temps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 5 :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
D&#039;après la fonction récursive Fibonacci définit par &amp;lt;br /&amp;gt;&lt;br /&gt;
f(0)=0 &amp;lt;br /&amp;gt;&lt;br /&gt;
f(1)=1 &amp;lt;br /&amp;gt;&lt;br /&gt;
f(n+2)=f(n+1)+f(n), &amp;lt;br /&amp;gt;&lt;br /&gt;
comment compter le nombre d&#039;appels récursifs en Caml? &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* la fonction renvoie une valeur de type int*int :&lt;br /&gt;
  - la première composante est la valeur de Fibonacci pour n,&lt;br /&gt;
  - la seconde composante est le nonbre d&#039;appels recursifs effectués *)&lt;br /&gt;
 let rec fib n =&lt;br /&gt;
     if (n&amp;lt;2) then (n,0)&lt;br /&gt;
     else let t = fib (n-1) in&lt;br /&gt;
          let s = fib (n-2) in &lt;br /&gt;
     (fst t + fst s , snd t + snd s + 1)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&#039;&#039;exemple : &#039;&#039;fib 10 = (55, 88) pour exécuter la fonction Fibonacci(10), il y a 88 appels récursifs nécessaires...&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exercice 2 : Listes&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 5 :&#039;&#039;&#039;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
suite à l&#039;étude des fonctions &lt;br /&gt;
*longueur&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec longueur l =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; 0&lt;br /&gt;
     | _::l -&amp;gt; 1 + longueur l&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*applique&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec app f p =&lt;br /&gt;
     match p with &lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
     | a :: p -&amp;gt; f(a) :: app f p&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*concatene&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec cat l1 l2 =&lt;br /&gt;
     match l1 with&lt;br /&gt;
     [] -&amp;gt; l2&lt;br /&gt;
     | a :: l -&amp;gt; a :: (cat l l2)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*renverse,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec renverse l =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
     | a :: l -&amp;gt; (renverse l) @ [a]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
on remarque des similitudes. Ces fonctions ont le même schéma de base. On peut résumer le principe commun dans la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec reduit l o f =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; o&lt;br /&gt;
     | a :: l -&amp;gt; let appel_rec = reduit l o f in&lt;br /&gt;
                 f a appel_rec&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&#039;&#039;NB :&#039;&#039; le type de &amp;lt;tt&amp;gt;reduit&amp;lt;/tt&amp;gt; donné par Caml est : &amp;lt;tt&amp;gt;val reduit : &#039;a list -&amp;gt; &#039;b -&amp;gt; (&#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b) -&amp;gt; &#039;b = &amp;lt;fun&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 6 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
Reprogrammons les fonctions précédentes à partir de la fonction reduit ! &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let longueur l =&lt;br /&gt;
     let f _ r = 1 + r in &lt;br /&gt;
     reduit l 0 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let app g l =&lt;br /&gt;
     let f a r = (g a)::r in&lt;br /&gt;
     reduit l [] f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let cat l1 l2 =&lt;br /&gt;
     let f a r = a :: r in  &lt;br /&gt;
     reduit l1 l2 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut également introduire la fonction directement avec un &amp;lt;tt&amp;gt;fun&amp;lt;/tt&amp;gt; de la maniere suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let renverse l = reduit l [] (fun a r -&amp;gt; r @ [a])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 7 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le type de la fonction reduit est: ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b ) -&amp;gt; &#039;a list &amp;lt;br/&amp;gt;&lt;br /&gt;
Celui de la fonction List.fold_right est: ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b ) -&amp;gt; &#039;a list -&amp;gt; &#039;b -&amp;gt; &#039;b  ;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
l&#039;ordre des arguments de fold_right est le même que l&#039;ordre des arguments de reduit. La fonction fold_right compte juste deux arguments supplémentaires.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 8 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici la fonction fold_left:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let rec fold_left f b l=&lt;br /&gt;
      match l with&lt;br /&gt;
        []-&amp;gt;b&lt;br /&gt;
       |a::l -&amp;gt; fold_left f (f b a) l;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Cette fonction est &#039;&#039;récursive terminale&#039;&#039;, de type ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;a ) -&amp;gt; &#039;a -&amp;gt; &#039;b list -&amp;gt; &#039;a .&lt;br /&gt;
&lt;br /&gt;
==Le TP1 - début==&lt;br /&gt;
&lt;br /&gt;
Le sujet [http://www.lama.univ-savoie.fr/~hyvernat/Enseignement/0809/info401/tp1.pdf programmes récursifs, listes], au format pdf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 1 : Quelques compléments sur les programmes récursifs&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans cette partie, on travaille sur la fonction Fibonacci&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On commence par l&#039;utiliser sous la forme :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib n =&lt;br /&gt;
if n&amp;lt;2&lt;br /&gt;
   then n&lt;br /&gt;
   else fib (n-1) + fib (n-2)&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comprendre ce qu&#039;il se passe, on trace la fonction à l&#039;aide de &amp;quot;#trace&amp;quot; pour fib 5&lt;br /&gt;
&lt;br /&gt;
fib &amp;lt;-- n veut dire que l&#039;on donne la valeur n à la fonction fib&lt;br /&gt;
&lt;br /&gt;
alors que fib --&amp;gt; n veut dire que fib renvoie n&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib 5 ;;&lt;br /&gt;
fib &amp;lt;-- 5&lt;br /&gt;
fib &amp;lt;-- 3&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib &amp;lt;-- 2&lt;br /&gt;
fib &amp;lt;-- 0&lt;br /&gt;
fib --&amp;gt; 0&lt;br /&gt;
...&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib &amp;lt;-- 2&lt;br /&gt;
fib &amp;lt;-- 0&lt;br /&gt;
fib --&amp;gt; 0&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib --&amp;gt; 2&lt;br /&gt;
fib --&amp;gt; 3&lt;br /&gt;
fib --&amp;gt; 5&lt;br /&gt;
- : int = 5&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut remarquer que la fonction calcule plusieurs fois le même fib n.&lt;br /&gt;
Une optimisation consisterait à garder certaines valeurs en mémoire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On écrit fib2 de type &amp;quot;int -&amp;gt; int*int&amp;quot; qui renvoie le valeur de fib n (fst fib2 n) et fib n-1 (snd (fib2 n)) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib2 n = &lt;br /&gt;
if n&amp;lt;2 &lt;br /&gt;
   then (n,n-1)&lt;br /&gt;
   else let t = fib2 (n-1) in&lt;br /&gt;
      (fst(t)+snd(t),fst(t));;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 3&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comparer les fonctions fib et fib2, on les trace pour n=7 :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib 7 ;;&lt;br /&gt;
fib &amp;lt;-- 7&lt;br /&gt;
fib &amp;lt;-- 5&lt;br /&gt;
fib &amp;lt;-- 3&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
...&lt;br /&gt;
fib --&amp;gt; 3&lt;br /&gt;
fib --&amp;gt; 5&lt;br /&gt;
fib --&amp;gt; 8&lt;br /&gt;
fib --&amp;gt; 13&lt;br /&gt;
- : int = 13&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib2 7 ;;&lt;br /&gt;
fib2 &amp;lt;-- 7&lt;br /&gt;
fib2 &amp;lt;-- 6&lt;br /&gt;
fib2 &amp;lt;-- 5&lt;br /&gt;
fib2 &amp;lt;-- 4&lt;br /&gt;
fib2 &amp;lt;-- 3&lt;br /&gt;
fib2 &amp;lt;-- 2&lt;br /&gt;
fib2 &amp;lt;-- 1&lt;br /&gt;
fib2 --&amp;gt; (1, 0)&lt;br /&gt;
fib2 --&amp;gt; (1, 1)&lt;br /&gt;
fib2 --&amp;gt; (2, 1)&lt;br /&gt;
fib2 --&amp;gt; (3, 2)&lt;br /&gt;
fib2 --&amp;gt; (5, 3)&lt;br /&gt;
fib2 --&amp;gt; (8, 5)&lt;br /&gt;
fib2 --&amp;gt; (13, 8)&lt;br /&gt;
- : int * int = (13, 8)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On remarque que fib2 fait 14 calculs alors que fib en 81 pour n=7.&lt;br /&gt;
Afin de retourner uniquement la valeur de fib n on définit une nouvelle fonction, beaucoup plus rapide que fib, &lt;br /&gt;
en prenant le premier élément de la paire constituant fib2 n :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let fib n = fst ( fib2 n ) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 4 ( Bonus )&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On veut créer fib3 de type int-&amp;gt;int-&amp;gt;int-&amp;gt;int tel que :&lt;br /&gt;
&lt;br /&gt;
- son premier argument est l&#039;entier n pour fibonacci de n&lt;br /&gt;
&lt;br /&gt;
- les 2 autres arguments sont des accumulateurs qui permettent de conserver des valeurs successives ( pour i-1 et i )&lt;br /&gt;
&lt;br /&gt;
 --- à venir ---&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 2 : Manipulation des listes&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici quelque fonctions définies en utilisant &amp;lt;tt&amp;gt;List.fold_right&amp;lt;/tt&amp;gt; :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let longueur l = let f a r = 1 + r in List.fold_right f l 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let app f l = let f&#039; a r = ( f a )::r in List.fold_right f&#039; l []&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let concat l1 l2 = let f a r = a::r in List.fold_right l1 l2 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici la fonction reverse telle qu&#039;on l&#039;a écrite dans le TD&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec reverse l = &lt;br /&gt;
  match l with&lt;br /&gt;
  []-&amp;gt;[]&lt;br /&gt;
  |a::l -&amp;gt; (reverse l)@[a] ;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour la comparer avec la fonction &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; de Caml, on va regarder le temps d&#039;exécution sur une très grande liste.&lt;br /&gt;
&lt;br /&gt;
Pour cela, on créé une fonction qui fabrique une liste de n valeurs :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec longueliste  n = &lt;br /&gt;
  if n=0 &lt;br /&gt;
  then []&lt;br /&gt;
  else n::longueliste (n-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut tester les fonctions avec une liste de 10000 éléments.&lt;br /&gt;
&lt;br /&gt;
La fonction &amp;lt;tt&amp;gt;reverse&amp;lt;/tt&amp;gt; met environ 15s alors que &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; s&#039;exécute immédiatement.&lt;br /&gt;
&lt;br /&gt;
Cela montre donc que &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; est bien plus efficace que &amp;lt;tt&amp;gt;reverse&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::En fait, reverse fait ( n + n-1 + n-2 + ... + 1 ) opérations à chaque fois (il met le premier élément au bout de la liste et ainsi de suite) , soit au total &amp;lt;math&amp;gt;n*(n+1)/2 \sim n^2&amp;lt;/math&amp;gt; opérations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; utilise la fonction suivante :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec rev_append l1 l2 =&lt;br /&gt;
  match l1 with&lt;br /&gt;
    [] -&amp;gt; l2&lt;br /&gt;
  | a::l -&amp;gt; rev_append l (a::l2);;&lt;br /&gt;
&lt;br /&gt;
let rec rev l = rev_append l [];;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Elle fait donc environ &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; opérations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 3 : Deux algorithmes de tri pour les listes&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On programme une fonction d&#039;insertion qui permet d&#039;insérer un élément à sa place&lt;br /&gt;
dans une liste triée.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insertion n l =&lt;br /&gt;
  match l with&lt;br /&gt;
    [] -&amp;gt; [n]&lt;br /&gt;
  | a::l&#039; -&amp;gt; if n&amp;lt;=a&lt;br /&gt;
             then n::l&lt;br /&gt;
             else a::(insertion n l&#039;) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On programme ensuite le tri par insertion.&lt;br /&gt;
&lt;br /&gt;
Le tri par insertion fonctionne de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
- la liste vide est triée,&lt;br /&gt;
&lt;br /&gt;
- pour trier la liste &amp;quot;&amp;lt;tt&amp;gt;a::l&amp;lt;/tt&amp;gt;&amp;quot;, on commence par trier (récursivement) la liste &amp;lt;tt&amp;gt;l&amp;lt;/tt&amp;gt;, puis on insère&lt;br /&gt;
l&#039;élément &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; dans le résultat.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec tri_insertion l =&lt;br /&gt;
 match l with&lt;br /&gt;
    [] -&amp;gt; []&lt;br /&gt;
  | a::l&#039; -&amp;gt; insertion a (tri_insertion l&#039;) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ou plus simplement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let tri l = List.fold.right insertion l [] ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 3&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Maintenant, on programme une fonction fusionne qui permet de fusionner deux listes triées en une seule liste triée.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionne l1 l2 =&lt;br /&gt;
  match l1 with &lt;br /&gt;
     [] -&amp;gt; l2&lt;br /&gt;
   | a::l&#039; -&amp;gt; begin&lt;br /&gt;
                match l2 with&lt;br /&gt;
                   [] -&amp;gt; l1&lt;br /&gt;
                 | b::l&#039;&#039; -&amp;gt; if a&amp;lt;=b then ( a::fusionne l&#039; l2 ) &lt;br /&gt;
                                     else ( b::fusionne l1 l&#039;&#039;) &lt;br /&gt;
&lt;br /&gt;
              end;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour éviter d&#039;imbriquer des &amp;quot;match&amp;quot;, on peut aussi filtrer directement la paire &amp;lt;tt&amp;gt;(l1,l2)&amp;lt;/tt&amp;gt; et regrouper les cas d&#039;un des listes vides ensemble : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionnebis l1 l2 =&lt;br /&gt;
  match l1,l2 with&lt;br /&gt;
      [],l | l,[]  -&amp;gt;  l&lt;br /&gt;
    | (a::l&#039;, b::l2&#039;)  -&amp;gt; &lt;br /&gt;
        if a &amp;lt;= b&lt;br /&gt;
        then a::(fusionnebis l&#039; l2)&lt;br /&gt;
        else b::(fusionnebis l1 l2&#039;)  ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 4&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis une fonction sépare qui permet de séparer une liste quelconque en&lt;br /&gt;
deux listes de taille équivalente&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec separe l =&lt;br /&gt;
  match l with&lt;br /&gt;
     [] -&amp;gt; ([],[])&lt;br /&gt;
   | [a] -&amp;gt; ([a],[])&lt;br /&gt;
   | a::b::l&#039; -&amp;gt; let t=separe l&#039; in (a::(fst t),b::(snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 5&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On doit maintenant programmer un deuxième type de tri : le tri par fusion.&lt;br /&gt;
&lt;br /&gt;
Le tri fusion fonctionne de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
- la liste vide est triée,&lt;br /&gt;
&lt;br /&gt;
- pour trier une liste non-vide, on sépare la liste en deux parties de longueur égale (à un&lt;br /&gt;
élément prêt), on trie (récursivement) ces deux listes, puis on fusionne les deux résultats.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec tri_fusion l =  &lt;br /&gt;
  match l with&lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
   | [a] -&amp;gt; [a]&lt;br /&gt;
   | _ -&amp;gt; let t=separe l in&lt;br /&gt;
          fusionne (tri_fusion (fst t)) (tri_fusion (snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 6&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comparer l&#039;efficacité des deux fonctions de tri, on utilise la même méthode que précédemment : &lt;br /&gt;
&lt;br /&gt;
On créé a l&#039;aide d&#039;un fonction une liste aléatoire de 10000 éléments, les éléments étant non triés.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let liste_aleatoire n =&lt;br /&gt;
  let rec aux n max = &lt;br /&gt;
    if n=0&lt;br /&gt;
    then []&lt;br /&gt;
    else (Random.int max)::aux (n-1) max&lt;br /&gt;
  in&lt;br /&gt;
  aux n n ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite on trie cette liste avec les deux fonctions.&lt;br /&gt;
&lt;br /&gt;
Le tri_fusion renvoie instantanément une liste de 10000 éléments aléatoires triés. &lt;br /&gt;
&lt;br /&gt;
Le tri insertion, quant à lui, prend plus d&#039;une dizaine de secondes.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;Remarque :&#039;&#039; cela vient du fait que le tri fusion divise la taille de la liste par deux à chaque étape, alors que le tri par insertion soustrait un élément à chaque étape.&lt;br /&gt;
: On peut montrer que le temps de calcul pour le tri fusion est proportionnel à &amp;lt;math&amp;gt;n \log(n)&amp;lt;/math&amp;gt;, ce qui est très petit par rapport à &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt; (temps d&#039;execution moyen du tri par insertion) quand &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; est grand.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 7&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On souhaite trier une liste selon la hauteur des points c&#039;est-à-dire selon le deuxième élément de la paire de flottants.&lt;br /&gt;
Pour cela, il faudrait faire un tri fusion sur le 2eme élément de la paire représentant les points&lt;br /&gt;
tout en sauvegardant le 1er élément...&lt;br /&gt;
&lt;br /&gt;
On peut créer une fonction de tri par fusion générale, qui prend comme paramètre une autre fonction (qui sert à vérifier la comparaison de 2 éléments et rend true ou false) afin de choisir le tri que l&#039;on veut ( décroissant, croissant ... ) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionne comp l1 l2 =&lt;br /&gt;
 match (l1,l2) with&lt;br /&gt;
    ([],_) -&amp;gt; l2&lt;br /&gt;
  | (_,[]) -&amp;gt; l1&lt;br /&gt;
  | (a::l&#039;, b::l2&#039;) -&amp;gt; &lt;br /&gt;
     if (comp a b)&lt;br /&gt;
     then a::(fusionne l&#039; l2)&lt;br /&gt;
     else b::(fusionne l1 l2&#039;);;&lt;br /&gt;
&lt;br /&gt;
let rec tri_fusion comp l =  &lt;br /&gt;
 match l with&lt;br /&gt;
    [] -&amp;gt; []&lt;br /&gt;
  | [a] -&amp;gt; [a]&lt;br /&gt;
  | _ -&amp;gt; let t=separe l in&lt;br /&gt;
         fusionne comp (tri_fusion comp (fst t)) (tri_fusion comp (snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il suffit alors a l&#039;utilisateur de définir la fonction de comparaison pour ensuite faire appel à &amp;lt;tt&amp;gt;tri_fusion&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Par exemple, pour trier dans un ordre décroissant :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let dec a n  = if a&amp;gt;=n then true&lt;br /&gt;
else false ;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
ou même plus simplement&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let dec = (&amp;gt;=) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour trier une liste de paires, il faut créer une fonction qui compare les seconds membres ;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let paire a n  = (snd a) &amp;lt;= (snd n)  ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ici, les paires seront triées selon le second membre dans l&#039;ordre croissant.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 8 ( Bonus )&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un algorithme de tri est dit stable quand il ne modifie pas l&#039;ordre relatifs des éléments &amp;quot;égaux&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Par exemple, on tri par ordre croissant du premier membre une liste de paires de float : [ ( 5 , 3 ) ; ( -2 , 8 ) ; ( -2 , 2 ) ; ( 5 , 8 ) ; ( 5 , -8 ) ]  &lt;br /&gt;
&lt;br /&gt;
non stable : &amp;lt;tt&amp;gt;[(-2, 2); (-2, 8); (5, -8); (5, 8); (5, 3)]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
stable : &amp;lt;tt&amp;gt;[(-2, 8); (-2, 2); (5, 3); (5, 8); (5, -8)]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour qu&#039;un tri soit stable, la comparaison de deux éléments doit comprendre aussi le &amp;quot;=&amp;quot;, comme c&#039;est le cas pour les fonctions paire et dec.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD3==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Exercice 1 : les arbres binaires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt; Question 1 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type &#039;a arbre = Vide | Noeud of &#039;a*&#039;a arbre*&#039;a arbre ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 2 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
let rec taille a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; 1 + (taille g) + (taille d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction taille compte le nombre de noeuds que contient un arbre.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 3 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec applique f a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; Vide&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; Noeud(f e,applique f g,applique f d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction applique est équivalente à la fonction List.map&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 4 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec poids (f : &#039;a -&amp;gt; int) a = &lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; (f e) + (poids f g) + (poids f d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 5 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec reduit a o f =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; let x = reduit g o f in&lt;br /&gt;
       			let y = reduit d o f in&lt;br /&gt;
                        f e x y ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction reduit est equivalente à la fonction List.fold_right pour le type des arbres.&lt;br /&gt;
&lt;br /&gt;
Réécriture de taille et poids :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec taille a = reduit a 0 (fun e x y -&amp;gt; 1 + x + y) ;;&lt;br /&gt;
let rec poids f a = reduit a 0 (fun e x y -&amp;gt; (f e) + (f x) + (f y)) ;; (*?????*)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 6 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec collecte a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; []&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; e::(collecte g)@(collecte d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction collecte récupère tous les éléments de l&#039;arbre et les renvoie sous forme d&#039;une liste.&lt;br /&gt;
&lt;br /&gt;
Avec la fonction reduit :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec collecte a = reduit a [] (fun e x y -&amp;gt; e::x@y) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 7 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec feuilles a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; []&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; if (g=Vide &amp;amp;&amp;amp; d=Vide) then [e]&lt;br /&gt;
       			else (feuilles g)@(feuilles d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Avec reduit :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec feuilles a = reduit a [] (fun e x y -&amp;gt; if (x=[] &amp;amp;&amp;amp; y=[]) then [e]&lt;br /&gt;
					       else x@y) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Exercice 2 : la tortue &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt; Question 1 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type action = Forward of int | Left of int | SetPos of int*int | SetHeading of int | PenUp | Pendown ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 2 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
let rec ecrit (l:action list) (pen:bool) : bool =&lt;br /&gt;
   match l with&lt;br /&gt;
    	[] -&amp;gt; false&lt;br /&gt;
       |(Forward d)::l -&amp;gt; if (d=0 || pen=false) then ecrit l pen&lt;br /&gt;
                          else true &lt;br /&gt;
       |PenUp::l -&amp;gt; ecrit l false&lt;br /&gt;
       |PenDown::l -&amp;gt; ecrit l true&lt;br /&gt;
       | _ -&amp;gt; ecrit l pen ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction ecrit renvoie true si la tortue écrit qqch ou false sinon.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 3 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec pos (x:int) (y:int) (a:int) (l:action list) : ((int*int)int) =&lt;br /&gt;
   match l with&lt;br /&gt;
    	[] -&amp;gt; ((x,y),a)&lt;br /&gt;
       |PenUp::l |Pendown::l -&amp;gt; pos x y a l&lt;br /&gt;
       |(Left b)::l -&amp;gt; pos x y (a+b) l&lt;br /&gt;
       |(SetPos(x&#039;,y&#039;))::l -&amp;gt; pos x&#039; y&#039; a l&lt;br /&gt;
       |(SetHeading b)::l -&amp;gt; pos x y b l &lt;br /&gt;
       |(Forward d)::l -&amp;gt; pos (x+(sin a)*d) (y+(cos a)*d) a l ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 5 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type action = Forward of int | SetPos of int*int | SetHeading of int | Left of int | PenUp | Pendown | Repeat of int*action list ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD4==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 1 : Petits exercices combinatoires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On commence par créer une fonction intermédiaire.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supp&#039; x l =&lt;br /&gt;
   match l with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |b::f&#039;-&amp;gt; if (x=b) then supp&#039; x l&#039;&lt;br /&gt;
                        else b::supp&#039; x f&#039;;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supp l =&lt;br /&gt;
   match l with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |a::l&#039;-&amp;gt; a::supp supp&#039; a l&#039;;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 2 : Dictionnaires &amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Un dictionnaire est une liste de paires&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Question 2 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insere c v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[(c,v)]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (c=c&#039;) then (c&#039;,v&#039;)::(insere c v d)&lt;br /&gt;
                               else (c,v)::d ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supprime c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (c=c&#039;) then d&lt;br /&gt;
                               else (c&#039;,v&#039;)::(supprime c d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec existe_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; false&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; (c=c&#039;) || existe_cle c d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec existe_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; false&lt;br /&gt;
      |(_,v&#039;)::d -&amp;gt; if (v=v&#039;) then true&lt;br /&gt;
                              else existe_val v d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec recherche_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; None&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; if (c=c&#039;) then Some c&#039;&lt;br /&gt;
                              else recherche_cle c d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* liste des valeurs de c par on peut avoir plusieurs cases, et donc plusieurs clés, avec une même valeur *)&lt;br /&gt;
let rec recherche_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (v=v&#039;) then c&#039;::(recherche_val v d)&lt;br /&gt;
                              else recherche_val v d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Liste des clés *)&lt;br /&gt;
let rec liste_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; []&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; c&#039;::(liste_cle c d);;&lt;br /&gt;
&lt;br /&gt;
(* Liste des valeurs *)&lt;br /&gt;
let rec liste_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(_,v&#039;)::d -&amp;gt; v&#039;::(liste_val v d);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut également utiliser des fonctions existantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Liste des clés *)&lt;br /&gt;
let liste_cle d = List.map fst;;&lt;br /&gt;
&lt;br /&gt;
(* Liste des valeurs, attention aux doublons! *)&lt;br /&gt;
let liste_val d = suppr_doublons(List.map snd);;&lt;br /&gt;
  &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 4 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec zip l1 l2&lt;br /&gt;
   match l1 l2 with&lt;br /&gt;
      [].[]-&amp;gt;[]&lt;br /&gt;
      |c::lc, v::lv -&amp;gt; (c,v)::(zip lc lv)&lt;br /&gt;
      |_,_ -&amp;gt; [];;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 5 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On aurait pu utiliser une liste triée : si par exemple on cherche 12 et qu&#039;on en est à 14 dans la liste, on sait que 12 n&#039;y est pas. PB : ceci n&#039;empêche pas d&#039;aller à la fin de la liste si la valeur ou la clé recherchée est grande ... &amp;lt;br/&amp;gt;&lt;br /&gt;
Une recherche dichotomique est inefficace sur les listes ... &amp;lt;br/&amp;gt;&lt;br /&gt;
   =&amp;gt; dans la bibliothèque hash table de Caml, il existe un List.zip&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 3 : Arbres binaires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Question 1 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
La profondeur d&#039;un arbre binaire correspond au nombre d&#039;étage : on regarde à partir de la première racine et des sous arbres, on calcule la profondeur à gauche et la profondeur à droite, on prend la plus grande et on y ajoute 1. &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec profondeur a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; 0&lt;br /&gt;
      |Noeud(_,g,d) -&amp;gt; 1 + max(profondeurg) (profondeurd);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 2 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec equilibre a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; true&lt;br /&gt;
      |Noeud(_,g,d) -&amp;gt; if (profondeur g)=(profondeur d) || (profondeur g)=(profondeur d +1) || (profondeur g +1)=(profondeur d)&lt;br /&gt;
                          then (equilibre d)&amp;amp;&amp;amp;(equilibre g)&lt;br /&gt;
                          else false;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec present e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; false&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; e&#039;=e || present e g || present e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 4 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec present e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; false&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; if (e&#039;=e) then true&lt;br /&gt;
                                  else  if (e&amp;lt;e&#039;) then present e g&lt;br /&gt;
                                                  else present e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 5 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insere e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; e&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; if (e&amp;lt;e&#039;) then insere e g&lt;br /&gt;
                                  else insere e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Le TP2==&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt;Partie 1&amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
QUESTION 1 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction suivante permet de calculer les ensemble de nombre. Elle est réalisé à l&#039;aide d&#039;une concaténation de la liste précédente avec la liste modifier ainsi que List.map.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
open List&lt;br /&gt;
&lt;br /&gt;
let rec sous_ensemble n=&lt;br /&gt;
    if n=0&lt;br /&gt;
    then &lt;br /&gt;
      [[]]&lt;br /&gt;
    else&lt;br /&gt;
      let liste = sous_ensemble (n-1) in (List.map (fun l-&amp;gt;n::l) liste) @ liste&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 2 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction supprime doublon est réalisé tout d&#039;abord en triant la liste puis en regardant si deux éléments concécutif sont les mêmes, si oui on en supprime un.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec lstTrier liste=&lt;br /&gt;
  match liste with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
    | [a]-&amp;gt;liste&lt;br /&gt;
    | a::b::liste-&amp;gt;if a=b then lstTrier (a::liste)&lt;br /&gt;
                          else a::lstTrier (b::liste)&lt;br /&gt;
&lt;br /&gt;
let supprime_doublon lst=&lt;br /&gt;
 lstTrier (List.sort (-) lst)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt;Partie 2&amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
QUESTION 1 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction taille calcul la taille d&#039;un arbre, on incrémente un compteur dès que l&#039;on rencontre un noeud. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec taille (arbre:&#039;a arbre)=&lt;br /&gt;
  match arbre  with&lt;br /&gt;
    Vide     -&amp;gt; 0&lt;br /&gt;
  | Noeud(_,a,b) -&amp;gt; 1 + taille a+taille b&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
la fonction applique permet d&#039;appliquer une fonction a tous les éléments d&#039;un arbre.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec applique (fc:&#039;a-&amp;gt;&#039;b) arbre=&lt;br /&gt;
  match arbre with&lt;br /&gt;
    Vide-&amp;gt;Vide&lt;br /&gt;
  | Noeud(a,b,c)-&amp;gt;Noeud (fc a,applique fc b,applique fc c )&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
la fonction fold renvoie le contenu des feuilles composant l&#039;arbre.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec fold (f:&#039;a-&amp;gt;&#039;b-&amp;gt;&#039;b-&amp;gt;&#039;b) arbre n=&lt;br /&gt;
  match arbre with&lt;br /&gt;
    Vide-&amp;gt;n&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;f a(fold f b n) (fold f c n)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 2 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction feuille crée une liste à partir des éléments retourné par la fonction fold.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec feuilles (f:&#039;a arbre-&amp;gt;&#039;a list) arbre=&lt;br /&gt;
  fold (fun a b c-&amp;gt; if(b=[])&amp;amp;&amp;amp;(c=[]) &lt;br /&gt;
     then [a] &lt;br /&gt;
     else (b@c)) arbre[]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 3 :&amp;lt;br/&amp;gt;&lt;br /&gt;
cette fonction permet de créer un arbre à partir d&#039;une liste, elle regarde la taille des branches afin de pouvoir inserer les éléments de façon à avoir le moins de noeuds possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec insert arbre aInsert=&lt;br /&gt;
  match arbre with&lt;br /&gt;
      Vide-&amp;gt;Noeud (aInsert,Vide,Vide)&lt;br /&gt;
    | Noeud (a,b,c)-&amp;gt;if (taille b &amp;lt; taille c) then Noeud(a,(insert b aInsert),c) else Noeud(a,b,(insert c aInsert))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
let rec construit_arbre_int liste arbre=&lt;br /&gt;
  match liste with &lt;br /&gt;
      [a]-&amp;gt;insert arbre a&lt;br /&gt;
    | a::liste-&amp;gt;construit_arbre_int liste (insert arbre a)&lt;br /&gt;
&lt;br /&gt;
let construit_arbre liste=&lt;br /&gt;
  construit_arbre_int liste Vide&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 4 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction se divise en deux partie : l&#039;une permet d&#039;obtenir la taille minimal d&#039;une branche et l&#039;autre la taille maximal, la fonction affiche ensuite les résultats.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec calcMax arbre compt=&lt;br /&gt;
match arbre with&lt;br /&gt;
    Vide-&amp;gt;compt&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;if (taille b &amp;gt; taille c) then calcMax b compt+1 else calcMax c compt+1&lt;br /&gt;
&lt;br /&gt;
let rec calcMin arbre compt=&lt;br /&gt;
match arbre with&lt;br /&gt;
    Vide-&amp;gt;compt&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;if (taille b &amp;lt; taille c) then calcMax b compt+1 else calcMax c compt+1&lt;br /&gt;
&lt;br /&gt;
let profondeurs arbre=&lt;br /&gt;
  (calcMax arbre 0 , calcMin arbre 0)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 5 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction tailleR est la fonction tille pour les arbres binaires.&amp;lt;br/&amp;gt;&lt;br /&gt;
nous pouvons remarquer que la fonction applique pourrait rendre un arbre binaire faux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
type &#039;a abr = Vide | Noeud of &#039;a abr * &#039;a* &#039;a abr&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
let rec tailleR abr=&lt;br /&gt;
  match abr with&lt;br /&gt;
    Vide     -&amp;gt; 0&lt;br /&gt;
  | Noeud(a,_,b) -&amp;gt; 1 + tailleR a+tailleR b&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 6 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction ajoute permet d&#039;ajouter une donnée en conservant un arbre binaire.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec ajoute arbre aInsert=&lt;br /&gt;
  match arbre with&lt;br /&gt;
      Vide-&amp;gt;Noeud (Vide,aInsert,Vide)&lt;br /&gt;
    | Noeud (a,b,c)-&amp;gt;if aInsert&amp;lt;b then Noeud((ajoute a aInsert),b,c) else Noeud(a,b,(ajoute c aInsert))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
QUESTION 7:&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction supp utilise aissi la fonction ajoute afin de conserver un arbre binaire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec supp arbre aSupp=&lt;br /&gt;
  match arbre with&lt;br /&gt;
      Vide-&amp;gt;Vide&lt;br /&gt;
    | Noeud (a,b,c)-&amp;gt;&lt;br /&gt;
	if (aSupp=b) &lt;br /&gt;
	then &lt;br /&gt;
	  if (a=Vide&amp;amp;&amp;amp;c=Vide)&lt;br /&gt;
	  then Vide&lt;br /&gt;
	  else&lt;br /&gt;
	    if (a=Vide&amp;amp;&amp;amp;c!=Vide)&lt;br /&gt;
	    then supp c aSupp&lt;br /&gt;
	    else&lt;br /&gt;
	      if (a!=Vide&amp;amp;&amp;amp;c=Vide)&lt;br /&gt;
	      then supp a aSupp&lt;br /&gt;
	      else&lt;br /&gt;
		ajouteArbre c a&lt;br /&gt;
	else Noeud((supp a aSupp),b,(supp c aSupp))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 8:&amp;lt;br/&amp;gt;&lt;br /&gt;
afin de verifier si un arbre est binaire on effectue deux match simultané a tous les noeuds rencontrés en parcourant l&#039;arbre.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec verifabr arbre=&lt;br /&gt;
match arbre with&lt;br /&gt;
    Vide-&amp;gt;true&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;&lt;br /&gt;
	  match a with&lt;br /&gt;
	      Vide-&amp;gt;true&lt;br /&gt;
	    | Noeud (a2,b2,c2)-&amp;gt;if b2&amp;lt;b then verifabr a else false&lt;br /&gt;
	&amp;amp;&amp;amp;&lt;br /&gt;
	  match c with&lt;br /&gt;
	      Vide-&amp;gt;true&lt;br /&gt;
	    | Noeud (a3,b3,c3)-&amp;gt;if b3&amp;gt;b then verifabr c else false&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
QUESTION 9:&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction trouveVal permet de renvoyer si oui ou non une valeur est présente dans l&#039;arbre binaire.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec trouveVal arbre valAtrouve=&lt;br /&gt;
match arbre with&lt;br /&gt;
    Vide-&amp;gt;false&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;&lt;br /&gt;
      if (b=valAtrouve)&lt;br /&gt;
      then true&lt;br /&gt;
      else&lt;br /&gt;
	if (valAtrouve&amp;lt;b)&lt;br /&gt;
	then trouveVal a valAtrouve&lt;br /&gt;
	else trouveVal c valAtrouve&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 10:&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction supprime_doublon sur un arbre binaire est plus complexe que celle sur les liste, en effet il faut vérifier aussi les doublons pouvant exister sur des branche séparé.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec suppDoublon arbre=&lt;br /&gt;
match arbre with&lt;br /&gt;
    Vide-&amp;gt;Vide&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;&lt;br /&gt;
	if (trouveVal a b)&lt;br /&gt;
	then&lt;br /&gt;
	  if (trouveVal c b)&lt;br /&gt;
	  then Noeud((suppDoublon(supp a b)),b,(suppDoublon(supp c b)))&lt;br /&gt;
	  else Noeud((suppDoublon(supp a b)),b,(suppDoublon c))&lt;br /&gt;
	else &lt;br /&gt;
	  if (trouveVal c b)&lt;br /&gt;
	  then Noeud((suppDoublon a),b,(suppDoublon(supp c b)))&lt;br /&gt;
	  else Noeud((suppDoublon a),b,(suppDoublon c))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Contrôle continu 1==&lt;br /&gt;
&#039;&#039;&#039;Partie 2&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
cette fonction s&#039;applique a tout les elements d&#039;une liste&lt;br /&gt;
&lt;br /&gt;
  &#039;&#039;&#039;let rec pam0 a l &#039;&#039;&#039;= &lt;br /&gt;
  match l with []-&amp;gt;[]&lt;br /&gt;
  |f::l-&amp;gt;(f a)::(pam0 a l);;                                                   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
la meme fonction mais cette fois on utilise Fold_right&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039; let pam a l&#039;&#039;&#039; = List.fold_right(fun f t -&amp;gt;(f a)::t)l [];;&lt;br /&gt;
&lt;br /&gt;
ou encore la version avec List.map,elle a le meme type que pam&lt;br /&gt;
  &#039;&#039;&#039;let pam1 a&#039;&#039;&#039; = List.map(fun f-&amp;gt;f a);;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 2&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   &#039;&#039;&#039;let rec seq i n&#039;&#039;&#039; = if n&amp;lt;i then []&lt;br /&gt;
   else (seq i(n-1))@[n];;&lt;br /&gt;
&lt;br /&gt;
   seq est du type:int-&amp;gt;int-&amp;gt;int list,cette fonction créee une liste&lt;br /&gt;
d&#039;entier consecutifs et concatène un element en fin de liste par exemple::&lt;br /&gt;
seq 5 14;; &lt;br /&gt;
   &#039;&#039;&#039;-:int list&#039;&#039;&#039; = [5;6;7;8;9;10;11;12;13;14]   &lt;br /&gt;
mais a partir de 5 chriffres l&#039;execution  met plus d&#039;une demi seconde &lt;br /&gt;
&lt;br /&gt;
essayons la version simple&lt;br /&gt;
   &#039;&#039;&#039;let rec seq1 i n&#039;&#039;&#039; = if n&amp;lt;i then [] else i::(seq(i+1)n);;&lt;br /&gt;
&lt;br /&gt;
la version recursive terminale avec un accumulateur nous permettons d&#039;avoir&lt;br /&gt;
une execution rapide de la fonction&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;&#039;let seq2 i n&#039;&#039;&#039; =&lt;br /&gt;
   &#039;&#039;&#039; let rec aux i n acc &#039;&#039;&#039;=&lt;br /&gt;
          if n&amp;lt;i then acc &lt;br /&gt;
          else aux i(n-1) (n::acc)&lt;br /&gt;
     in &lt;br /&gt;
     aux i n [];; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Partie 3&#039;&#039;&#039;&lt;br /&gt;
suite de robinson&lt;br /&gt;
ecrivons d&#039;abord une iteration qui nous permet de repéter&lt;br /&gt;
l&#039;action sur la fonction&lt;br /&gt;
    &#039;&#039;&#039;let rec iter f n x&#039;&#039;&#039; = if n=0 then x else iter f(n-1)(f x);;&lt;br /&gt;
ensuite la fonction suivant pour passer d&#039;un terme a l&#039;autre&lt;br /&gt;
   &#039;&#039;&#039; let suivant u &#039;&#039;&#039;= &lt;br /&gt;
    (*nous avons aussi la fonction aux permettant de compter le nombre de fois&lt;br /&gt;
             ou d apparait dans n*)&lt;br /&gt;
   &#039;&#039;&#039; let rec aux u n d &#039;&#039;&#039;= match u with []-&amp;gt;n::d::[]&lt;br /&gt;
    |a::u when a=d -&amp;gt; aux u (n+1) d&lt;br /&gt;
    |a::u-&amp;gt;n::d::(aux u 1 a)&lt;br /&gt;
    in &lt;br /&gt;
    &#039;&#039;&#039;let u &#039;&#039;&#039;= List.sort(fun x y-&amp;gt;y-x)u (*et la fonction u qui nous permet de trier par ordre &lt;br /&gt;
    decroissant en utilisant List.sort*)&lt;br /&gt;
    in &lt;br /&gt;
    match u with []-&amp;gt;[]&lt;br /&gt;
    |a::u-&amp;gt; aux u 1 a;;&lt;br /&gt;
&lt;br /&gt;
==Le TP3==&lt;br /&gt;
&#039;&#039;&#039;Partie 1&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 1&#039;&#039;&#039;&lt;br /&gt;
Déclaration du type pour les tas ( &#039;a tas )&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;type &#039;a tas = Vide | Noeud of &#039;a * &#039;a tas * &#039;a tas ;;&amp;lt;/source&amp;gt;&lt;br /&gt;
La fonction pour tester si un élement de type &#039;a tas est effectivement un tas : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;let rec test tas vPrec = match tas with&lt;br /&gt;
    Noeud(v,t1,t2) -&amp;gt; if v &amp;gt;= vPrec &lt;br /&gt;
                        then ((test t1 v)&amp;amp;(test t2 v))&lt;br /&gt;
                        else false&lt;br /&gt;
  |Vide -&amp;gt; true&lt;br /&gt;
&lt;br /&gt;
let testTas tas = match tas with  &lt;br /&gt;
   Noeud(v,_,_) -&amp;gt; test tas v &lt;br /&gt;
  |Vide -&amp;gt; true &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 2&#039;&#039;&#039;&lt;br /&gt;
Pour cette question nous allons écrire 3 fonctions.&lt;br /&gt;
La première a pour but de supprimer le premier élément du tas (donc le plus petit), la seconde a pour but de retourner la valeur du premier élément du tas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;(*Enleve le premier element du tas&lt;br /&gt;
&lt;br /&gt;
 Explication du nom de variables&lt;br /&gt;
   tgv -&amp;gt; tas gauche valeur ( valeur du tas de gauche)&lt;br /&gt;
   tgg -&amp;gt; tas gauche gauche ( le tas gauche du tas gauche)&lt;br /&gt;
   tgd -&amp;gt; tas gauche droit ( le tas droit du tas gauche)&lt;br /&gt;
*)&lt;br /&gt;
let rec enlever tas = match tas with&lt;br /&gt;
     Vide -&amp;gt; Vide                             (* Si le tas est vide on retourne le tas Vide *)&lt;br /&gt;
|    Noeud (v,Vide,td) -&amp;gt; td                  (* Si le tas gauche est Vide on retourne le tas droit *) &lt;br /&gt;
|    Noeud (v,tg,Vide) -&amp;gt; tg                  (* Si le tas droit est Vide on retourne le tas gauche *)&lt;br /&gt;
|    Noeud (v, (Noeud (tgv,tgg,tgd) as tg),   &lt;br /&gt;
               (Noeud (tdv,tdg,tdd) as td))   (* Si aucun des deux tas est vide *)&lt;br /&gt;
     -&amp;gt; if tgv &amp;lt; tdv&lt;br /&gt;
       then Noeud (tgv, enlever tg, td)   &lt;br /&gt;
       else Noeud (tdv, tg, enlever td);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Renvoie la valeur du premier element du tas *)&lt;br /&gt;
let premier tas = match tas with &lt;br /&gt;
    Vide -&amp;gt; raise Tas_Vide&lt;br /&gt;
  | Noeud(v,_,_) -&amp;gt; v ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On combine ces deux fonctions pour crée la fonction demandée.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let min_tas tas = ((premier tas),(enlever tas));;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 3&#039;&#039;&#039;&lt;br /&gt;
Nous allons crée un fonction qui va calculer la taille de la plus petite branche du tas et de la plus grande branche du tas.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* compare les taille max et les taille min des tas calculé par la fonction tailleTas *)&lt;br /&gt;
let compare a b = match (a,b) with &lt;br /&gt;
    ((amin,amax),(bmin,bmax)) -&amp;gt; ((min amin bmin),(max amax bmax));;&lt;br /&gt;
&lt;br /&gt;
(* ajoute 1 a la taille du tas *)&lt;br /&gt;
let add a = match a with &lt;br /&gt;
    (min,max)-&amp;gt; ((min+1),(max+1));;&lt;br /&gt;
&lt;br /&gt;
(* retourne la taille max et la taille min d&#039;un tas *)&lt;br /&gt;
let rec tailleTas tas = match tas with&lt;br /&gt;
    Vide -&amp;gt; (0,0)&lt;br /&gt;
  | Noeud(_,tg,td) -&amp;gt; add (compare (tailleTas tg) (tailleTas td));;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite il suffit d&#039;utiliser cette fonction sur le tas et de comparer l&#039;écart entre la branche la plus courte et la branche la plus longue.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let equilibre tas = match (tailleTas tas) with&lt;br /&gt;
    (min,max) -&amp;gt; (max - min)&amp;lt;2 ;;  (* on calcule la difference entre max et min et on test si elle est inférieur à 2 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 4&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* ajoute un element a un tas *)&lt;br /&gt;
let rec ajouter v tas = match tas with&lt;br /&gt;
     Vide -&amp;gt; Noeud (v,Vide,Vide)&lt;br /&gt;
|    Noeud (tv,tg,td) -&amp;gt; Noeud( min tv v, td, ajouter (max tv v) tg);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
on insère systématiquement dans le tas de droite, mais on permute le tas de gauche et le tas de droite a chaque fois pour &amp;quot;mélanger&amp;quot; le tas et avoir un tas équilibré&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 5&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* ajoute une liste d’elements a un tas *)&lt;br /&gt;
let rec ajList liste tas = match liste with&lt;br /&gt;
     [] -&amp;gt; tas&lt;br /&gt;
|    v::l&#039; -&amp;gt; ajouter v (ajList l&#039; tas);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Il s&#039;agit d&#039;une simple fonction récursive qui parcours la liste et fais appel a la fonction ajouter pour chaque élément de la liste.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;à finir&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 6&#039;&#039;&#039;&lt;br /&gt;
Pour implémenter le tri par tas, nous allons commencer par créer une fonction qui vide un tas et renvoie le contenu de celui-ci dans une liste triée.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* vide un tas et renvoie le contenu du tas dans une liste triée *)&lt;br /&gt;
let rec viderTas tas = match tas with&lt;br /&gt;
     Vide -&amp;gt; []&lt;br /&gt;
|    Noeud (x,_,_) -&amp;gt; (premier tas)::(viderTas (enlever tas)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il nous suffit maintenant de crée un tas avec la liste en utilisant la fonction ajList, et de passer la liste ainsi crée en paramètre a la fonction viderTas. &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* tri la liste passée en paramètre avec la méthode du tri par tas *)&lt;br /&gt;
let triTas lst = viderTas (ajList lst Vide);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;à finir&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Le TD5==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TP4==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==TD6==&lt;/div&gt;</summary>
		<author><name>Laurent corantin</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=INFO401_corr_TD_TP&amp;diff=4171</id>
		<title>INFO401 corr TD TP</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=INFO401_corr_TD_TP&amp;diff=4171"/>
		<updated>2009-05-22T11:55:33Z</updated>

		<summary type="html">&lt;p&gt;Laurent corantin : /* Le TP2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Préliminaires==&lt;br /&gt;
&lt;br /&gt;
Pour afficher correctement dans le wiki, allez voir un peu comment on fait. Vous pouvez regarder par exemple sur le [[INFO401 | wiki du cours]] ou directement sur des articles de [http://fr.wikipedia.org/wiki/Accueil Wikipedia]. La documentation de mediawiki se trouve [http://meta.wikimedia.org/wiki/Aide:Éditeur ici].&lt;br /&gt;
&lt;br /&gt;
Un truc important : pour rentrer du code Caml, il faut mettre les balises &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;...&amp;lt;/source&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; autour de votre code. Allez par exemple voir le début de la section sur [[#Le TD1 et le TP0 | le TD1 et TP0]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vous pouvez aller discuter des corrections dans les sujets de discussions associes...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD1 et le TP0==&lt;br /&gt;
&lt;br /&gt;
Pour vous montrer un exemple de ce que j&#039;attends, voila la correction de la fonction factorielle. (C&#039;était facile...) J&#039;ai volontairement mis beaucoup de commentaires...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;La fonction factorielle (TD1, exercice 2, question 2)&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but est de calculer la fonction &amp;lt;math&amp;gt;!n = 1\times2\times \cdots \times n&amp;lt;/math&amp;gt; par récurrence. La version typée est verbeuse de la fonction correspondante en Caml donne :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* fonction factorielle : c&#039;est la factorielle habituelle des mathématiciens... *)&lt;br /&gt;
let rec fact (n:int) : int =&lt;br /&gt;
  if (n&amp;gt;1)&lt;br /&gt;
  then  n * (fact (n-1))&lt;br /&gt;
  else 1      (* rq : pour que le programme ne boucle pas sur les valeurs négatives, on renvoie 1 dés que n&amp;lt;1 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme la fonction est récursive, il ne faut pas oublier le &amp;lt;tt&amp;gt;rec&amp;lt;/tt&amp;gt; au début de la définition.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On aurait pu faire une autre version, qui fonctionne différemment sur les nombres négatifs :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fact&#039; = function&lt;br /&gt;
   n when (n&amp;gt;0) -&amp;gt; n * fact&#039; (n-1)&lt;br /&gt;
 | n when (n&amp;lt;0) -&amp;gt; n * fact&#039; (n+1)&lt;br /&gt;
 | _ -&amp;gt; 1  (* si n n&#039;est ni plus petit que 0 ni plus grand que 0, n est égal à 0, et on renvoie donc 1 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;ai volontairement mis une version qui contient plusieurs choses que nous n&#039;avons pas encore vues en cours :&lt;br /&gt;
* utilisation de &amp;quot;&amp;lt;tt&amp;gt;function&amp;lt;/tt&amp;gt;&amp;quot; plutôt que &amp;lt;tt&amp;gt;fun&amp;lt;/tt&amp;gt;,&lt;br /&gt;
* le symbole &amp;quot;&amp;lt;tt&amp;gt;|&amp;lt;/tt&amp;gt;&amp;quot;,&lt;br /&gt;
* le mot clé &amp;quot;&amp;lt;tt&amp;gt;when&amp;lt;/tt&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Vous devriez pouvoir comprendre ce que fait la fonction. Sinon, voici une version que vous auriez pu écrire :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fact_bis = fun n -&amp;gt;&lt;br /&gt;
  if (n=0)&lt;br /&gt;
  then 1&lt;br /&gt;
  else begin&lt;br /&gt;
    if (n&amp;gt;0)&lt;br /&gt;
    then n*fact_bis (n-1)&lt;br /&gt;
    else n*fact_bis (n+1)   (* dans ce cas, n est forcement négatif *)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Les fonctions sommes &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il s&#039;agit ici d&#039;écrire la fonction qui va additionner les carrés des entiers de 1 jusqu&#039;à un nombre donné.&lt;br /&gt;
&lt;br /&gt;
Cela donne :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_carre b =&lt;br /&gt;
if (b=0) then 0&lt;br /&gt;
else (b*b) + somme_carre (b-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite on nous demande de calculer la somme des cubes des entiers de 1 jusqu&#039;à un nombre donné. On pourrait faire le même programme en remplaçant b*b par b*b*b, mais on va définir une fonction puissance (car elle n&#039;existe pas d&#039;origine sous Caml), qui nous servira aussi pour la suite... :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec puissance x a =&lt;br /&gt;
if (a = 0) then 1&lt;br /&gt;
else x * puissance x (a-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On doit maintenant calculer la somme des &amp;lt;math&amp;gt;i^i&amp;lt;/math&amp;gt;, i variant de 1 à un nombre donné :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_puissance b =&lt;br /&gt;
if (b=0) then 0&lt;br /&gt;
else (puissance b b) + somme_puissance (b-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut définir une unique fonction qui permettrait de faire toutes ces sommes, celle-ci aura pour argument une fonction quelconque :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_fonction n f = (* f étant une fonction *)&lt;br /&gt;
if (n=0) then f 0&lt;br /&gt;
else f n + somme_fonction (n-1) f;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
cette fonction est de type &amp;quot;&amp;lt;tt&amp;gt;int -&amp;gt; fun -&amp;gt; int&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Nombres pairs et impairs (TP0 Partie 2 Question 2) &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut écrire les fonctions récursives pairs et impairs, qui renvoient vrai si le nombre est pair (respectivement impair) et faux si le nombre est impair (respectivement pair);&lt;br /&gt;
Ici nous devons déclarer simultanément les deux fonctions, car chacune fait appel à l&#039;autre lors de son exécution.&lt;br /&gt;
&lt;br /&gt;
Cela donne :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec pair n =&lt;br /&gt;
  if (n=0) then true&lt;br /&gt;
  else impair (n-1)&lt;br /&gt;
and impair n =&lt;br /&gt;
  if (n=0) then false&lt;br /&gt;
  else  pair (n-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Suite de Fibonacci &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La suite de fibonacci est tel que u&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;=0 u&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;=1 et u&amp;lt;sub&amp;gt;n+2&amp;lt;/sub&amp;gt;=u&amp;lt;sub&amp;gt;n+1&amp;lt;/sub&amp;gt;+u&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib n =&lt;br /&gt;
if (n=0) then 0&lt;br /&gt;
else if (n=1) then 1&lt;br /&gt;
else fib (n-1) + fib (n-2);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La plus grande valeur que l&#039;on peut obtenir sans que cela soit trop long est 24157817, ce qui correspond à fib 37.&lt;br /&gt;
Nous trouvons qu&#039;il faut déjà 88 additions pour calculer fib 10.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Rq :&#039;&#039;&#039; fib de 37 prend effectivement beaucoup de temps. Il faut 39088168 additions avant d&#039;en arriver à bout. Il est possible de faire une version de Fibonacci qui va très vite et qui calcule &amp;lt;tt&amp;gt;fib 37&amp;lt;/tt&amp;gt; en seulement 36 additions...&lt;br /&gt;
: Comment ?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Dragon ! &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;i&amp;gt; Le dragon est une créature mythique, présente dans de nombreuses cultures.&lt;br /&gt;
  On peut déterminer deux grands types de dragons : le dragon occidental et le dragon oriental&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction dragon a pour but de dessiner un dragon, pour cela on utilise une fonction récursive qui admet pour argument le nombre n d&#039;itération de la fonction, et les coordonnées de 2 points. A chaque itération, la fonction calcule pour chaque segment, un nouveau point et le relie ensuite aux deux autres.&lt;br /&gt;
&lt;br /&gt;
On obtient en tout 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; segments entremêlés, qui forment un dragon.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s go !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec dragon (n:int) (a:int) (b:int) (c:int) (d:int) : unit =&lt;br /&gt;
if (n = 0) then (moveto a b ; lineto c d)&lt;br /&gt;
               else begin&lt;br /&gt;
                      let x = (a+c+d-b)/2 in&lt;br /&gt;
                      let y = (b+d+a-c)/2 in&lt;br /&gt;
                      dragon (n-1) a b x y ;&lt;br /&gt;
                      dragon (n-1) c d x y&lt;br /&gt;
                    end ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Rq : &#039;&#039;&#039; votre version du dragon est bien, mais pas très précises. (Je chipote un peu...)  Pour les paramètres (&amp;lt;tt&amp;gt;dragon 11 100 100 400 400&amp;lt;/tt&amp;gt;), de nombreux carrés ne sont pas bien tracés.&lt;br /&gt;
:Comment expliquez-vous cela, et comment pouvez-vous le corriger ?&lt;br /&gt;
&lt;br /&gt;
::Pour améliorer la précision je suggère de passer les coordonnées en type Float. --[[Utilisateur:Nicolas|Nicolas]] 31 janvier 2009 à 11:42 (CET)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD2==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exercice 1 : Tuples&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 4 :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
On définit la fonction curry par:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let curry (f: &#039;a * &#039;b -&amp;gt; &#039;c) : &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;c&lt;br /&gt;
     = fun x y -&amp;gt; f(x,y);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ou encore en simplifiant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let curry f x y = f(x,y);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On définit ensuite la fonction uncurry par:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry (f: &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;c) : &#039;a * &#039;b -&amp;gt; &#039;c&lt;br /&gt;
     = fun x -&amp;gt; f (fst x) (snd x);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ou encore de trois autres manières plus simplifiées:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = fun x -&amp;gt; f (fst x) (snd x);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = fun x -&amp;gt; match x with (a,b) -&amp;gt; f a b;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = function (a,b) -&amp;gt; f a b;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Avantage de la première forme (à plusieurs arguments): Elle permet une application partielle: on peut appliquer cette fonction à une seule partie des arguments.&lt;br /&gt;
&lt;br /&gt;
Inconvénients de la seconde forme (à un argument): &lt;br /&gt;
*il faut faire appel à fst, snd;&lt;br /&gt;
*Caml doit séparer les paires: c&#039;est une perte de temps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 5 :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
D&#039;après la fonction récursive Fibonacci définit par &amp;lt;br /&amp;gt;&lt;br /&gt;
f(0)=0 &amp;lt;br /&amp;gt;&lt;br /&gt;
f(1)=1 &amp;lt;br /&amp;gt;&lt;br /&gt;
f(n+2)=f(n+1)+f(n), &amp;lt;br /&amp;gt;&lt;br /&gt;
comment compter le nombre d&#039;appels récursifs en Caml? &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* la fonction renvoie une valeur de type int*int :&lt;br /&gt;
  - la première composante est la valeur de Fibonacci pour n,&lt;br /&gt;
  - la seconde composante est le nonbre d&#039;appels recursifs effectués *)&lt;br /&gt;
 let rec fib n =&lt;br /&gt;
     if (n&amp;lt;2) then (n,0)&lt;br /&gt;
     else let t = fib (n-1) in&lt;br /&gt;
          let s = fib (n-2) in &lt;br /&gt;
     (fst t + fst s , snd t + snd s + 1)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&#039;&#039;exemple : &#039;&#039;fib 10 = (55, 88) pour exécuter la fonction Fibonacci(10), il y a 88 appels récursifs nécessaires...&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exercice 2 : Listes&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 5 :&#039;&#039;&#039;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
suite à l&#039;étude des fonctions &lt;br /&gt;
*longueur&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec longueur l =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; 0&lt;br /&gt;
     | _::l -&amp;gt; 1 + longueur l&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*applique&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec app f p =&lt;br /&gt;
     match p with &lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
     | a :: p -&amp;gt; f(a) :: app f p&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*concatene&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec cat l1 l2 =&lt;br /&gt;
     match l1 with&lt;br /&gt;
     [] -&amp;gt; l2&lt;br /&gt;
     | a :: l -&amp;gt; a :: (cat l l2)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*renverse,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec renverse l =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
     | a :: l -&amp;gt; (renverse l) @ [a]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
on remarque des similitudes. Ces fonctions ont le même schéma de base. On peut résumer le principe commun dans la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec reduit l o f =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; o&lt;br /&gt;
     | a :: l -&amp;gt; let appel_rec = reduit l o f in&lt;br /&gt;
                 f a appel_rec&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&#039;&#039;NB :&#039;&#039; le type de &amp;lt;tt&amp;gt;reduit&amp;lt;/tt&amp;gt; donné par Caml est : &amp;lt;tt&amp;gt;val reduit : &#039;a list -&amp;gt; &#039;b -&amp;gt; (&#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b) -&amp;gt; &#039;b = &amp;lt;fun&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 6 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
Reprogrammons les fonctions précédentes à partir de la fonction reduit ! &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let longueur l =&lt;br /&gt;
     let f _ r = 1 + r in &lt;br /&gt;
     reduit l 0 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let app g l =&lt;br /&gt;
     let f a r = (g a)::r in&lt;br /&gt;
     reduit l [] f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let cat l1 l2 =&lt;br /&gt;
     let f a r = a :: r in  &lt;br /&gt;
     reduit l1 l2 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut également introduire la fonction directement avec un &amp;lt;tt&amp;gt;fun&amp;lt;/tt&amp;gt; de la maniere suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let renverse l = reduit l [] (fun a r -&amp;gt; r @ [a])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 7 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le type de la fonction reduit est: ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b ) -&amp;gt; &#039;a list &amp;lt;br/&amp;gt;&lt;br /&gt;
Celui de la fonction List.fold_right est: ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b ) -&amp;gt; &#039;a list -&amp;gt; &#039;b -&amp;gt; &#039;b  ;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
l&#039;ordre des arguments de fold_right est le même que l&#039;ordre des arguments de reduit. La fonction fold_right compte juste deux arguments supplémentaires.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 8 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici la fonction fold_left:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let rec fold_left f b l=&lt;br /&gt;
      match l with&lt;br /&gt;
        []-&amp;gt;b&lt;br /&gt;
       |a::l -&amp;gt; fold_left f (f b a) l;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Cette fonction est &#039;&#039;récursive terminale&#039;&#039;, de type ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;a ) -&amp;gt; &#039;a -&amp;gt; &#039;b list -&amp;gt; &#039;a .&lt;br /&gt;
&lt;br /&gt;
==Le TP1 - début==&lt;br /&gt;
&lt;br /&gt;
Le sujet [http://www.lama.univ-savoie.fr/~hyvernat/Enseignement/0809/info401/tp1.pdf programmes récursifs, listes], au format pdf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 1 : Quelques compléments sur les programmes récursifs&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans cette partie, on travaille sur la fonction Fibonacci&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On commence par l&#039;utiliser sous la forme :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib n =&lt;br /&gt;
if n&amp;lt;2&lt;br /&gt;
   then n&lt;br /&gt;
   else fib (n-1) + fib (n-2)&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comprendre ce qu&#039;il se passe, on trace la fonction à l&#039;aide de &amp;quot;#trace&amp;quot; pour fib 5&lt;br /&gt;
&lt;br /&gt;
fib &amp;lt;-- n veut dire que l&#039;on donne la valeur n à la fonction fib&lt;br /&gt;
&lt;br /&gt;
alors que fib --&amp;gt; n veut dire que fib renvoie n&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib 5 ;;&lt;br /&gt;
fib &amp;lt;-- 5&lt;br /&gt;
fib &amp;lt;-- 3&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib &amp;lt;-- 2&lt;br /&gt;
fib &amp;lt;-- 0&lt;br /&gt;
fib --&amp;gt; 0&lt;br /&gt;
...&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib &amp;lt;-- 2&lt;br /&gt;
fib &amp;lt;-- 0&lt;br /&gt;
fib --&amp;gt; 0&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib --&amp;gt; 2&lt;br /&gt;
fib --&amp;gt; 3&lt;br /&gt;
fib --&amp;gt; 5&lt;br /&gt;
- : int = 5&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut remarquer que la fonction calcule plusieurs fois le même fib n.&lt;br /&gt;
Une optimisation consisterait à garder certaines valeurs en mémoire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On écrit fib2 de type &amp;quot;int -&amp;gt; int*int&amp;quot; qui renvoie le valeur de fib n (fst fib2 n) et fib n-1 (snd (fib2 n)) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib2 n = &lt;br /&gt;
if n&amp;lt;2 &lt;br /&gt;
   then (n,n-1)&lt;br /&gt;
   else let t = fib2 (n-1) in&lt;br /&gt;
      (fst(t)+snd(t),fst(t));;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 3&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comparer les fonctions fib et fib2, on les trace pour n=7 :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib 7 ;;&lt;br /&gt;
fib &amp;lt;-- 7&lt;br /&gt;
fib &amp;lt;-- 5&lt;br /&gt;
fib &amp;lt;-- 3&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
...&lt;br /&gt;
fib --&amp;gt; 3&lt;br /&gt;
fib --&amp;gt; 5&lt;br /&gt;
fib --&amp;gt; 8&lt;br /&gt;
fib --&amp;gt; 13&lt;br /&gt;
- : int = 13&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib2 7 ;;&lt;br /&gt;
fib2 &amp;lt;-- 7&lt;br /&gt;
fib2 &amp;lt;-- 6&lt;br /&gt;
fib2 &amp;lt;-- 5&lt;br /&gt;
fib2 &amp;lt;-- 4&lt;br /&gt;
fib2 &amp;lt;-- 3&lt;br /&gt;
fib2 &amp;lt;-- 2&lt;br /&gt;
fib2 &amp;lt;-- 1&lt;br /&gt;
fib2 --&amp;gt; (1, 0)&lt;br /&gt;
fib2 --&amp;gt; (1, 1)&lt;br /&gt;
fib2 --&amp;gt; (2, 1)&lt;br /&gt;
fib2 --&amp;gt; (3, 2)&lt;br /&gt;
fib2 --&amp;gt; (5, 3)&lt;br /&gt;
fib2 --&amp;gt; (8, 5)&lt;br /&gt;
fib2 --&amp;gt; (13, 8)&lt;br /&gt;
- : int * int = (13, 8)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On remarque que fib2 fait 14 calculs alors que fib en 81 pour n=7.&lt;br /&gt;
Afin de retourner uniquement la valeur de fib n on définit une nouvelle fonction, beaucoup plus rapide que fib, &lt;br /&gt;
en prenant le premier élément de la paire constituant fib2 n :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let fib n = fst ( fib2 n ) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 4 ( Bonus )&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On veut créer fib3 de type int-&amp;gt;int-&amp;gt;int-&amp;gt;int tel que :&lt;br /&gt;
&lt;br /&gt;
- son premier argument est l&#039;entier n pour fibonacci de n&lt;br /&gt;
&lt;br /&gt;
- les 2 autres arguments sont des accumulateurs qui permettent de conserver des valeurs successives ( pour i-1 et i )&lt;br /&gt;
&lt;br /&gt;
 --- à venir ---&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 2 : Manipulation des listes&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici quelque fonctions définies en utilisant &amp;lt;tt&amp;gt;List.fold_right&amp;lt;/tt&amp;gt; :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let longueur l = let f a r = 1 + r in List.fold_right f l 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let app f l = let f&#039; a r = ( f a )::r in List.fold_right f&#039; l []&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let concat l1 l2 = let f a r = a::r in List.fold_right l1 l2 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici la fonction reverse telle qu&#039;on l&#039;a écrite dans le TD&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec reverse l = &lt;br /&gt;
  match l with&lt;br /&gt;
  []-&amp;gt;[]&lt;br /&gt;
  |a::l -&amp;gt; (reverse l)@[a] ;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour la comparer avec la fonction &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; de Caml, on va regarder le temps d&#039;exécution sur une très grande liste.&lt;br /&gt;
&lt;br /&gt;
Pour cela, on créé une fonction qui fabrique une liste de n valeurs :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec longueliste  n = &lt;br /&gt;
  if n=0 &lt;br /&gt;
  then []&lt;br /&gt;
  else n::longueliste (n-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut tester les fonctions avec une liste de 10000 éléments.&lt;br /&gt;
&lt;br /&gt;
La fonction &amp;lt;tt&amp;gt;reverse&amp;lt;/tt&amp;gt; met environ 15s alors que &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; s&#039;exécute immédiatement.&lt;br /&gt;
&lt;br /&gt;
Cela montre donc que &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; est bien plus efficace que &amp;lt;tt&amp;gt;reverse&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::En fait, reverse fait ( n + n-1 + n-2 + ... + 1 ) opérations à chaque fois (il met le premier élément au bout de la liste et ainsi de suite) , soit au total &amp;lt;math&amp;gt;n*(n+1)/2 \sim n^2&amp;lt;/math&amp;gt; opérations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; utilise la fonction suivante :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec rev_append l1 l2 =&lt;br /&gt;
  match l1 with&lt;br /&gt;
    [] -&amp;gt; l2&lt;br /&gt;
  | a::l -&amp;gt; rev_append l (a::l2);;&lt;br /&gt;
&lt;br /&gt;
let rec rev l = rev_append l [];;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Elle fait donc environ &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; opérations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 3 : Deux algorithmes de tri pour les listes&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On programme une fonction d&#039;insertion qui permet d&#039;insérer un élément à sa place&lt;br /&gt;
dans une liste triée.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insertion n l =&lt;br /&gt;
  match l with&lt;br /&gt;
    [] -&amp;gt; [n]&lt;br /&gt;
  | a::l&#039; -&amp;gt; if n&amp;lt;=a&lt;br /&gt;
             then n::l&lt;br /&gt;
             else a::(insertion n l&#039;) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On programme ensuite le tri par insertion.&lt;br /&gt;
&lt;br /&gt;
Le tri par insertion fonctionne de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
- la liste vide est triée,&lt;br /&gt;
&lt;br /&gt;
- pour trier la liste &amp;quot;&amp;lt;tt&amp;gt;a::l&amp;lt;/tt&amp;gt;&amp;quot;, on commence par trier (récursivement) la liste &amp;lt;tt&amp;gt;l&amp;lt;/tt&amp;gt;, puis on insère&lt;br /&gt;
l&#039;élément &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; dans le résultat.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec tri_insertion l =&lt;br /&gt;
 match l with&lt;br /&gt;
    [] -&amp;gt; []&lt;br /&gt;
  | a::l&#039; -&amp;gt; insertion a (tri_insertion l&#039;) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ou plus simplement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let tri l = List.fold.right insertion l [] ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 3&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Maintenant, on programme une fonction fusionne qui permet de fusionner deux listes triées en une seule liste triée.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionne l1 l2 =&lt;br /&gt;
  match l1 with &lt;br /&gt;
     [] -&amp;gt; l2&lt;br /&gt;
   | a::l&#039; -&amp;gt; begin&lt;br /&gt;
                match l2 with&lt;br /&gt;
                   [] -&amp;gt; l1&lt;br /&gt;
                 | b::l&#039;&#039; -&amp;gt; if a&amp;lt;=b then ( a::fusionne l&#039; l2 ) &lt;br /&gt;
                                     else ( b::fusionne l1 l&#039;&#039;) &lt;br /&gt;
&lt;br /&gt;
              end;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour éviter d&#039;imbriquer des &amp;quot;match&amp;quot;, on peut aussi filtrer directement la paire &amp;lt;tt&amp;gt;(l1,l2)&amp;lt;/tt&amp;gt; et regrouper les cas d&#039;un des listes vides ensemble : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionnebis l1 l2 =&lt;br /&gt;
  match l1,l2 with&lt;br /&gt;
      [],l | l,[]  -&amp;gt;  l&lt;br /&gt;
    | (a::l&#039;, b::l2&#039;)  -&amp;gt; &lt;br /&gt;
        if a &amp;lt;= b&lt;br /&gt;
        then a::(fusionnebis l&#039; l2)&lt;br /&gt;
        else b::(fusionnebis l1 l2&#039;)  ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 4&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis une fonction sépare qui permet de séparer une liste quelconque en&lt;br /&gt;
deux listes de taille équivalente&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec separe l =&lt;br /&gt;
  match l with&lt;br /&gt;
     [] -&amp;gt; ([],[])&lt;br /&gt;
   | [a] -&amp;gt; ([a],[])&lt;br /&gt;
   | a::b::l&#039; -&amp;gt; let t=separe l&#039; in (a::(fst t),b::(snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 5&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On doit maintenant programmer un deuxième type de tri : le tri par fusion.&lt;br /&gt;
&lt;br /&gt;
Le tri fusion fonctionne de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
- la liste vide est triée,&lt;br /&gt;
&lt;br /&gt;
- pour trier une liste non-vide, on sépare la liste en deux parties de longueur égale (à un&lt;br /&gt;
élément prêt), on trie (récursivement) ces deux listes, puis on fusionne les deux résultats.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec tri_fusion l =  &lt;br /&gt;
  match l with&lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
   | [a] -&amp;gt; [a]&lt;br /&gt;
   | _ -&amp;gt; let t=separe l in&lt;br /&gt;
          fusionne (tri_fusion (fst t)) (tri_fusion (snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 6&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comparer l&#039;efficacité des deux fonctions de tri, on utilise la même méthode que précédemment : &lt;br /&gt;
&lt;br /&gt;
On créé a l&#039;aide d&#039;un fonction une liste aléatoire de 10000 éléments, les éléments étant non triés.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let liste_aleatoire n =&lt;br /&gt;
  let rec aux n max = &lt;br /&gt;
    if n=0&lt;br /&gt;
    then []&lt;br /&gt;
    else (Random.int max)::aux (n-1) max&lt;br /&gt;
  in&lt;br /&gt;
  aux n n ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite on trie cette liste avec les deux fonctions.&lt;br /&gt;
&lt;br /&gt;
Le tri_fusion renvoie instantanément une liste de 10000 éléments aléatoires triés. &lt;br /&gt;
&lt;br /&gt;
Le tri insertion, quant à lui, prend plus d&#039;une dizaine de secondes.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;Remarque :&#039;&#039; cela vient du fait que le tri fusion divise la taille de la liste par deux à chaque étape, alors que le tri par insertion soustrait un élément à chaque étape.&lt;br /&gt;
: On peut montrer que le temps de calcul pour le tri fusion est proportionnel à &amp;lt;math&amp;gt;n \log(n)&amp;lt;/math&amp;gt;, ce qui est très petit par rapport à &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt; (temps d&#039;execution moyen du tri par insertion) quand &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; est grand.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 7&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On souhaite trier une liste selon la hauteur des points c&#039;est-à-dire selon le deuxième élément de la paire de flottants.&lt;br /&gt;
Pour cela, il faudrait faire un tri fusion sur le 2eme élément de la paire représentant les points&lt;br /&gt;
tout en sauvegardant le 1er élément...&lt;br /&gt;
&lt;br /&gt;
On peut créer une fonction de tri par fusion générale, qui prend comme paramètre une autre fonction (qui sert à vérifier la comparaison de 2 éléments et rend true ou false) afin de choisir le tri que l&#039;on veut ( décroissant, croissant ... ) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionne comp l1 l2 =&lt;br /&gt;
 match (l1,l2) with&lt;br /&gt;
    ([],_) -&amp;gt; l2&lt;br /&gt;
  | (_,[]) -&amp;gt; l1&lt;br /&gt;
  | (a::l&#039;, b::l2&#039;) -&amp;gt; &lt;br /&gt;
     if (comp a b)&lt;br /&gt;
     then a::(fusionne l&#039; l2)&lt;br /&gt;
     else b::(fusionne l1 l2&#039;);;&lt;br /&gt;
&lt;br /&gt;
let rec tri_fusion comp l =  &lt;br /&gt;
 match l with&lt;br /&gt;
    [] -&amp;gt; []&lt;br /&gt;
  | [a] -&amp;gt; [a]&lt;br /&gt;
  | _ -&amp;gt; let t=separe l in&lt;br /&gt;
         fusionne comp (tri_fusion comp (fst t)) (tri_fusion comp (snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il suffit alors a l&#039;utilisateur de définir la fonction de comparaison pour ensuite faire appel à &amp;lt;tt&amp;gt;tri_fusion&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Par exemple, pour trier dans un ordre décroissant :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let dec a n  = if a&amp;gt;=n then true&lt;br /&gt;
else false ;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
ou même plus simplement&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let dec = (&amp;gt;=) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour trier une liste de paires, il faut créer une fonction qui compare les seconds membres ;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let paire a n  = (snd a) &amp;lt;= (snd n)  ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ici, les paires seront triées selon le second membre dans l&#039;ordre croissant.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 8 ( Bonus )&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un algorithme de tri est dit stable quand il ne modifie pas l&#039;ordre relatifs des éléments &amp;quot;égaux&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Par exemple, on tri par ordre croissant du premier membre une liste de paires de float : [ ( 5 , 3 ) ; ( -2 , 8 ) ; ( -2 , 2 ) ; ( 5 , 8 ) ; ( 5 , -8 ) ]  &lt;br /&gt;
&lt;br /&gt;
non stable : &amp;lt;tt&amp;gt;[(-2, 2); (-2, 8); (5, -8); (5, 8); (5, 3)]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
stable : &amp;lt;tt&amp;gt;[(-2, 8); (-2, 2); (5, 3); (5, 8); (5, -8)]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour qu&#039;un tri soit stable, la comparaison de deux éléments doit comprendre aussi le &amp;quot;=&amp;quot;, comme c&#039;est le cas pour les fonctions paire et dec.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD3==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Exercice 1 : les arbres binaires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt; Question 1 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type &#039;a arbre = Vide | Noeud of &#039;a*&#039;a arbre*&#039;a arbre ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 2 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
let rec taille a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; 1 + (taille g) + (taille d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction taille compte le nombre de noeuds que contient un arbre.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 3 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec applique f a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; Vide&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; Noeud(f e,applique f g,applique f d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction applique est équivalente à la fonction List.map&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 4 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec poids (f : &#039;a -&amp;gt; int) a = &lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; (f e) + (poids f g) + (poids f d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 5 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec reduit a o f =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; let x = reduit g o f in&lt;br /&gt;
       			let y = reduit d o f in&lt;br /&gt;
                        f e x y ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction reduit est equivalente à la fonction List.fold_right pour le type des arbres.&lt;br /&gt;
&lt;br /&gt;
Réécriture de taille et poids :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec taille a = reduit a 0 (fun e x y -&amp;gt; 1 + x + y) ;;&lt;br /&gt;
let rec poids f a = reduit a 0 (fun e x y -&amp;gt; (f e) + (f x) + (f y)) ;; (*?????*)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 6 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec collecte a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; []&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; e::(collecte g)@(collecte d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction collecte récupère tous les éléments de l&#039;arbre et les renvoie sous forme d&#039;une liste.&lt;br /&gt;
&lt;br /&gt;
Avec la fonction reduit :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec collecte a = reduit a [] (fun e x y -&amp;gt; e::x@y) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 7 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec feuilles a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; []&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; if (g=Vide &amp;amp;&amp;amp; d=Vide) then [e]&lt;br /&gt;
       			else (feuilles g)@(feuilles d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Avec reduit :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec feuilles a = reduit a [] (fun e x y -&amp;gt; if (x=[] &amp;amp;&amp;amp; y=[]) then [e]&lt;br /&gt;
					       else x@y) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Exercice 2 : la tortue &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt; Question 1 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type action = Forward of int | Left of int | SetPos of int*int | SetHeading of int | PenUp | Pendown ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 2 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
let rec ecrit (l:action list) (pen:bool) : bool =&lt;br /&gt;
   match l with&lt;br /&gt;
    	[] -&amp;gt; false&lt;br /&gt;
       |(Forward d)::l -&amp;gt; if (d=0 || pen=false) then ecrit l pen&lt;br /&gt;
                          else true &lt;br /&gt;
       |PenUp::l -&amp;gt; ecrit l false&lt;br /&gt;
       |PenDown::l -&amp;gt; ecrit l true&lt;br /&gt;
       | _ -&amp;gt; ecrit l pen ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction ecrit renvoie true si la tortue écrit qqch ou false sinon.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 3 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec pos (x:int) (y:int) (a:int) (l:action list) : ((int*int)int) =&lt;br /&gt;
   match l with&lt;br /&gt;
    	[] -&amp;gt; ((x,y),a)&lt;br /&gt;
       |PenUp::l |Pendown::l -&amp;gt; pos x y a l&lt;br /&gt;
       |(Left b)::l -&amp;gt; pos x y (a+b) l&lt;br /&gt;
       |(SetPos(x&#039;,y&#039;))::l -&amp;gt; pos x&#039; y&#039; a l&lt;br /&gt;
       |(SetHeading b)::l -&amp;gt; pos x y b l &lt;br /&gt;
       |(Forward d)::l -&amp;gt; pos (x+(sin a)*d) (y+(cos a)*d) a l ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 5 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type action = Forward of int | SetPos of int*int | SetHeading of int | Left of int | PenUp | Pendown | Repeat of int*action list ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD4==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 1 : Petits exercices combinatoires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On commence par créer une fonction intermédiaire.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supp&#039; x l =&lt;br /&gt;
   match l with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |b::f&#039;-&amp;gt; if (x=b) then supp&#039; x l&#039;&lt;br /&gt;
                        else b::supp&#039; x f&#039;;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supp l =&lt;br /&gt;
   match l with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |a::l&#039;-&amp;gt; a::supp supp&#039; a l&#039;;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 2 : Dictionnaires &amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Un dictionnaire est une liste de paires&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Question 2 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insere c v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[(c,v)]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (c=c&#039;) then (c&#039;,v&#039;)::(insere c v d)&lt;br /&gt;
                               else (c,v)::d ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supprime c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (c=c&#039;) then d&lt;br /&gt;
                               else (c&#039;,v&#039;)::(supprime c d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec existe_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; false&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; (c=c&#039;) || existe_cle c d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec existe_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; false&lt;br /&gt;
      |(_,v&#039;)::d -&amp;gt; if (v=v&#039;) then true&lt;br /&gt;
                              else existe_val v d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec recherche_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; None&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; if (c=c&#039;) then Some c&#039;&lt;br /&gt;
                              else recherche_cle c d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* liste des valeurs de c par on peut avoir plusieurs cases, et donc plusieurs clés, avec une même valeur *)&lt;br /&gt;
let rec recherche_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (v=v&#039;) then c&#039;::(recherche_val v d)&lt;br /&gt;
                              else recherche_val v d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Liste des clés *)&lt;br /&gt;
let rec liste_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; []&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; c&#039;::(liste_cle c d);;&lt;br /&gt;
&lt;br /&gt;
(* Liste des valeurs *)&lt;br /&gt;
let rec liste_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(_,v&#039;)::d -&amp;gt; v&#039;::(liste_val v d);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut également utiliser des fonctions existantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Liste des clés *)&lt;br /&gt;
let liste_cle d = List.map fst;;&lt;br /&gt;
&lt;br /&gt;
(* Liste des valeurs, attention aux doublons! *)&lt;br /&gt;
let liste_val d = suppr_doublons(List.map snd);;&lt;br /&gt;
  &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 4 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec zip l1 l2&lt;br /&gt;
   match l1 l2 with&lt;br /&gt;
      [].[]-&amp;gt;[]&lt;br /&gt;
      |c::lc, v::lv -&amp;gt; (c,v)::(zip lc lv)&lt;br /&gt;
      |_,_ -&amp;gt; [];;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 5 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On aurait pu utiliser une liste triée : si par exemple on cherche 12 et qu&#039;on en est à 14 dans la liste, on sait que 12 n&#039;y est pas. PB : ceci n&#039;empêche pas d&#039;aller à la fin de la liste si la valeur ou la clé recherchée est grande ... &amp;lt;br/&amp;gt;&lt;br /&gt;
Une recherche dichotomique est inefficace sur les listes ... &amp;lt;br/&amp;gt;&lt;br /&gt;
   =&amp;gt; dans la bibliothèque hash table de Caml, il existe un List.zip&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 3 : Arbres binaires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Question 1 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
La profondeur d&#039;un arbre binaire correspond au nombre d&#039;étage : on regarde à partir de la première racine et des sous arbres, on calcule la profondeur à gauche et la profondeur à droite, on prend la plus grande et on y ajoute 1. &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec profondeur a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; 0&lt;br /&gt;
      |Noeud(_,g,d) -&amp;gt; 1 + max(profondeurg) (profondeurd);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 2 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec equilibre a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; true&lt;br /&gt;
      |Noeud(_,g,d) -&amp;gt; if (profondeur g)=(profondeur d) || (profondeur g)=(profondeur d +1) || (profondeur g +1)=(profondeur d)&lt;br /&gt;
                          then (equilibre d)&amp;amp;&amp;amp;(equilibre g)&lt;br /&gt;
                          else false;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec present e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; false&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; e&#039;=e || present e g || present e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 4 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec present e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; false&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; if (e&#039;=e) then true&lt;br /&gt;
                                  else  if (e&amp;lt;e&#039;) then present e g&lt;br /&gt;
                                                  else present e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 5 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insere e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; e&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; if (e&amp;lt;e&#039;) then insere e g&lt;br /&gt;
                                  else insere e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Le TP2==&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt;Partie 1&amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
QUESTION 1 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction suivante permet de calculer les ensemble de nombre. Elle est réalisé à l&#039;aide d&#039;une concaténation de la liste précédente avec la liste modifier ainsi que List.map.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
open List&lt;br /&gt;
&lt;br /&gt;
let rec sous_ensemble n=&lt;br /&gt;
    if n=0&lt;br /&gt;
    then &lt;br /&gt;
      [[]]&lt;br /&gt;
    else&lt;br /&gt;
      let liste = sous_ensemble (n-1) in (List.map (fun l-&amp;gt;n::l) liste) @ liste&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 2 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction supprime doublon est réalisé tout d&#039;abord en triant la liste puis en regardant si deux éléments concécutif sont les mêmes, si oui on en supprime un.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec lstTrier liste=&lt;br /&gt;
  match liste with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
    | [a]-&amp;gt;liste&lt;br /&gt;
    | a::b::liste-&amp;gt;if a=b then lstTrier (a::liste)&lt;br /&gt;
                          else a::lstTrier (b::liste)&lt;br /&gt;
&lt;br /&gt;
let supprime_doublon lst=&lt;br /&gt;
 lstTrier (List.sort (-) lst)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt;Partie 2&amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
QUESTION 1 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction taille calcul la taille d&#039;un arbre, on incrémente un compteur dès que l&#039;on rencontre un noeud. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec taille (arbre:&#039;a arbre)=&lt;br /&gt;
  match arbre  with&lt;br /&gt;
    Vide     -&amp;gt; 0&lt;br /&gt;
  | Noeud(_,a,b) -&amp;gt; 1 + taille a+taille b&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
la fonction applique permet d&#039;appliquer une fonction a tous les éléments d&#039;un arbre.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec applique (fc:&#039;a-&amp;gt;&#039;b) arbre=&lt;br /&gt;
  match arbre with&lt;br /&gt;
    Vide-&amp;gt;Vide&lt;br /&gt;
  | Noeud(a,b,c)-&amp;gt;Noeud (fc a,applique fc b,applique fc c )&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
la fonction fold renvoie le contenu des feuilles composant l&#039;arbre.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec fold (f:&#039;a-&amp;gt;&#039;b-&amp;gt;&#039;b-&amp;gt;&#039;b) arbre n=&lt;br /&gt;
  match arbre with&lt;br /&gt;
    Vide-&amp;gt;n&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;f a(fold f b n) (fold f c n)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 2 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction feuille crée une liste à partir des éléments retourné par la fonction fold.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec feuilles (f:&#039;a arbre-&amp;gt;&#039;a list) arbre=&lt;br /&gt;
  fold (fun a b c-&amp;gt; if(b=[])&amp;amp;&amp;amp;(c=[]) &lt;br /&gt;
     then [a] &lt;br /&gt;
     else (b@c)) arbre[]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 3 :&amp;lt;br/&amp;gt;&lt;br /&gt;
cette fonction permet de créer un arbre à partir d&#039;une liste, elle regarde la taille des branches afin de pouvoir inserer les éléments de façon à avoir le moins de noeuds possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec insert arbre aInsert=&lt;br /&gt;
  match arbre with&lt;br /&gt;
      Vide-&amp;gt;Noeud (aInsert,Vide,Vide)&lt;br /&gt;
    | Noeud (a,b,c)-&amp;gt;if (taille b &amp;lt; taille c) then Noeud(a,(insert b aInsert),c) else Noeud(a,b,(insert c aInsert))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
let rec construit_arbre_int liste arbre=&lt;br /&gt;
  match liste with &lt;br /&gt;
      [a]-&amp;gt;insert arbre a&lt;br /&gt;
    | a::liste-&amp;gt;construit_arbre_int liste (insert arbre a)&lt;br /&gt;
&lt;br /&gt;
let construit_arbre liste=&lt;br /&gt;
  construit_arbre_int liste Vide&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 4 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction se divise en deux partie : l&#039;une permet d&#039;obtenir la taille minimal d&#039;une branche et l&#039;autre la taille maximal, la fonction affiche ensuite les résultats.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec calcMax arbre compt=&lt;br /&gt;
match arbre with&lt;br /&gt;
    Vide-&amp;gt;compt&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;if (taille b &amp;gt; taille c) then calcMax b compt+1 else calcMax c compt+1&lt;br /&gt;
&lt;br /&gt;
let rec calcMin arbre compt=&lt;br /&gt;
match arbre with&lt;br /&gt;
    Vide-&amp;gt;compt&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;if (taille b &amp;lt; taille c) then calcMax b compt+1 else calcMax c compt+1&lt;br /&gt;
&lt;br /&gt;
let profondeurs arbre=&lt;br /&gt;
  (calcMax arbre 0 , calcMin arbre 0)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 5 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction tailleR est la fonction tille pour les arbres binaires.&amp;lt;br/&amp;gt;&lt;br /&gt;
nous pouvons remarquer que la fonction applique pourrait rendre un arbre binaire faux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
type &#039;a abr = Vide | Noeud of &#039;a abr * &#039;a* &#039;a abr&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
let rec tailleR abr=&lt;br /&gt;
  match abr with&lt;br /&gt;
    Vide     -&amp;gt; 0&lt;br /&gt;
  | Noeud(a,_,b) -&amp;gt; 1 + tailleR a+tailleR b&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 6 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction ajoute permet d&#039;ajouter une donnée en conservant un arbre binaire.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec ajoute arbre aInsert=&lt;br /&gt;
  match arbre with&lt;br /&gt;
      Vide-&amp;gt;Noeud (Vide,aInsert,Vide)&lt;br /&gt;
    | Noeud (a,b,c)-&amp;gt;if aInsert&amp;lt;b then Noeud((ajoute a aInsert),b,c) else Noeud(a,b,(ajoute c aInsert))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
QUESTION 7:&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction supp utilise aissi la fonction ajoute afin de conserver un arbre binaire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec supp arbre aSupp=&lt;br /&gt;
  match arbre with&lt;br /&gt;
      Vide-&amp;gt;Vide&lt;br /&gt;
    | Noeud (a,b,c)-&amp;gt;&lt;br /&gt;
	if (aSupp=b) &lt;br /&gt;
	then &lt;br /&gt;
	  if (a=Vide&amp;amp;&amp;amp;c=Vide)&lt;br /&gt;
	  then Vide&lt;br /&gt;
	  else&lt;br /&gt;
	    if (a=Vide&amp;amp;&amp;amp;c!=Vide)&lt;br /&gt;
	    then supp c aSupp&lt;br /&gt;
	    else&lt;br /&gt;
	      if (a!=Vide&amp;amp;&amp;amp;c=Vide)&lt;br /&gt;
	      then supp a aSupp&lt;br /&gt;
	      else&lt;br /&gt;
		ajouteArbre c a&lt;br /&gt;
	else Noeud((supp a aSupp),b,(supp c aSupp))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 8:&amp;lt;br/&amp;gt;&lt;br /&gt;
afin de verifier si un arbre est binaire on effectue deux match simultané a tous les noeuds rencontrés en parcourant l&#039;arbre.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec verifabr arbre=&lt;br /&gt;
match arbre with&lt;br /&gt;
    Vide-&amp;gt;true&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;&lt;br /&gt;
	  match a with&lt;br /&gt;
	      Vide-&amp;gt;true&lt;br /&gt;
	    | Noeud (a2,b2,c2)-&amp;gt;if b2&amp;lt;b then verifabr a else false&lt;br /&gt;
	&amp;amp;&amp;amp;&lt;br /&gt;
	  match c with&lt;br /&gt;
	      Vide-&amp;gt;true&lt;br /&gt;
	    | Noeud (a3,b3,c3)-&amp;gt;if b3&amp;gt;b then verifabr c else false&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Contrôle continu 1==&lt;br /&gt;
&#039;&#039;&#039;Partie 2&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
cette fonction s&#039;applique a tout les elements d&#039;une liste&lt;br /&gt;
&lt;br /&gt;
  &#039;&#039;&#039;let rec pam0 a l &#039;&#039;&#039;= &lt;br /&gt;
  match l with []-&amp;gt;[]&lt;br /&gt;
  |f::l-&amp;gt;(f a)::(pam0 a l);;                                                   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
la meme fonction mais cette fois on utilise Fold_right&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039; let pam a l&#039;&#039;&#039; = List.fold_right(fun f t -&amp;gt;(f a)::t)l [];;&lt;br /&gt;
&lt;br /&gt;
ou encore la version avec List.map,elle a le meme type que pam&lt;br /&gt;
  &#039;&#039;&#039;let pam1 a&#039;&#039;&#039; = List.map(fun f-&amp;gt;f a);;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 2&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   &#039;&#039;&#039;let rec seq i n&#039;&#039;&#039; = if n&amp;lt;i then []&lt;br /&gt;
   else (seq i(n-1))@[n];;&lt;br /&gt;
&lt;br /&gt;
   seq est du type:int-&amp;gt;int-&amp;gt;int list,cette fonction créee une liste&lt;br /&gt;
d&#039;entier consecutifs et concatène un element en fin de liste par exemple::&lt;br /&gt;
seq 5 14;; &lt;br /&gt;
   &#039;&#039;&#039;-:int list&#039;&#039;&#039; = [5;6;7;8;9;10;11;12;13;14]   &lt;br /&gt;
mais a partir de 5 chriffres l&#039;execution  met plus d&#039;une demi seconde &lt;br /&gt;
&lt;br /&gt;
essayons la version simple&lt;br /&gt;
   &#039;&#039;&#039;let rec seq1 i n&#039;&#039;&#039; = if n&amp;lt;i then [] else i::(seq(i+1)n);;&lt;br /&gt;
&lt;br /&gt;
la version recursive terminale avec un accumulateur nous permettons d&#039;avoir&lt;br /&gt;
une execution rapide de la fonction&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;&#039;let seq2 i n&#039;&#039;&#039; =&lt;br /&gt;
   &#039;&#039;&#039; let rec aux i n acc &#039;&#039;&#039;=&lt;br /&gt;
          if n&amp;lt;i then acc &lt;br /&gt;
          else aux i(n-1) (n::acc)&lt;br /&gt;
     in &lt;br /&gt;
     aux i n [];; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Partie 3&#039;&#039;&#039;&lt;br /&gt;
suite de robinson&lt;br /&gt;
ecrivons d&#039;abord une iteration qui nous permet de repéter&lt;br /&gt;
l&#039;action sur la fonction&lt;br /&gt;
    &#039;&#039;&#039;let rec iter f n x&#039;&#039;&#039; = if n=0 then x else iter f(n-1)(f x);;&lt;br /&gt;
ensuite la fonction suivant pour passer d&#039;un terme a l&#039;autre&lt;br /&gt;
   &#039;&#039;&#039; let suivant u &#039;&#039;&#039;= &lt;br /&gt;
    (*nous avons aussi la fonction aux permettant de compter le nombre de fois&lt;br /&gt;
             ou d apparait dans n*)&lt;br /&gt;
   &#039;&#039;&#039; let rec aux u n d &#039;&#039;&#039;= match u with []-&amp;gt;n::d::[]&lt;br /&gt;
    |a::u when a=d -&amp;gt; aux u (n+1) d&lt;br /&gt;
    |a::u-&amp;gt;n::d::(aux u 1 a)&lt;br /&gt;
    in &lt;br /&gt;
    &#039;&#039;&#039;let u &#039;&#039;&#039;= List.sort(fun x y-&amp;gt;y-x)u (*et la fonction u qui nous permet de trier par ordre &lt;br /&gt;
    decroissant en utilisant List.sort*)&lt;br /&gt;
    in &lt;br /&gt;
    match u with []-&amp;gt;[]&lt;br /&gt;
    |a::u-&amp;gt; aux u 1 a;;&lt;br /&gt;
&lt;br /&gt;
==Le TP3==&lt;br /&gt;
&#039;&#039;&#039;Partie 1&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 1&#039;&#039;&#039;&lt;br /&gt;
Déclaration du type pour les tas ( &#039;a tas )&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;type &#039;a tas = Vide | Noeud of &#039;a * &#039;a tas * &#039;a tas ;;&amp;lt;/source&amp;gt;&lt;br /&gt;
La fonction pour tester si un élement de type &#039;a tas est effectivement un tas : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;let rec test tas vPrec = match tas with&lt;br /&gt;
    Noeud(v,t1,t2) -&amp;gt; if v &amp;gt;= vPrec &lt;br /&gt;
                        then ((test t1 v)&amp;amp;(test t2 v))&lt;br /&gt;
                        else false&lt;br /&gt;
  |Vide -&amp;gt; true&lt;br /&gt;
&lt;br /&gt;
let testTas tas = match tas with  &lt;br /&gt;
   Noeud(v,_,_) -&amp;gt; test tas v &lt;br /&gt;
  |Vide -&amp;gt; true &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 2&#039;&#039;&#039;&lt;br /&gt;
Pour cette question nous allons écrire 3 fonctions.&lt;br /&gt;
La première a pour but de supprimer le premier élément du tas (donc le plus petit), la seconde a pour but de retourner la valeur du premier élément du tas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;(*Enleve le premier element du tas&lt;br /&gt;
&lt;br /&gt;
 Explication du nom de variables&lt;br /&gt;
   tgv -&amp;gt; tas gauche valeur ( valeur du tas de gauche)&lt;br /&gt;
   tgg -&amp;gt; tas gauche gauche ( le tas gauche du tas gauche)&lt;br /&gt;
   tgd -&amp;gt; tas gauche droit ( le tas droit du tas gauche)&lt;br /&gt;
*)&lt;br /&gt;
let rec enlever tas = match tas with&lt;br /&gt;
     Vide -&amp;gt; Vide                             (* Si le tas est vide on retourne le tas Vide *)&lt;br /&gt;
|    Noeud (v,Vide,td) -&amp;gt; td                  (* Si le tas gauche est Vide on retourne le tas droit *) &lt;br /&gt;
|    Noeud (v,tg,Vide) -&amp;gt; tg                  (* Si le tas droit est Vide on retourne le tas gauche *)&lt;br /&gt;
|    Noeud (v, (Noeud (tgv,tgg,tgd) as tg),   &lt;br /&gt;
               (Noeud (tdv,tdg,tdd) as td))   (* Si aucun des deux tas est vide *)&lt;br /&gt;
     -&amp;gt; if tgv &amp;lt; tdv&lt;br /&gt;
       then Noeud (tgv, enlever tg, td)   &lt;br /&gt;
       else Noeud (tdv, tg, enlever td);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Renvoie la valeur du premier element du tas *)&lt;br /&gt;
let premier tas = match tas with &lt;br /&gt;
    Vide -&amp;gt; raise Tas_Vide&lt;br /&gt;
  | Noeud(v,_,_) -&amp;gt; v ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On combine ces deux fonctions pour crée la fonction demandée.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let min_tas tas = ((premier tas),(enlever tas));;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 3&#039;&#039;&#039;&lt;br /&gt;
Nous allons crée un fonction qui va calculer la taille de la plus petite branche du tas et de la plus grande branche du tas.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* compare les taille max et les taille min des tas calculé par la fonction tailleTas *)&lt;br /&gt;
let compare a b = match (a,b) with &lt;br /&gt;
    ((amin,amax),(bmin,bmax)) -&amp;gt; ((min amin bmin),(max amax bmax));;&lt;br /&gt;
&lt;br /&gt;
(* ajoute 1 a la taille du tas *)&lt;br /&gt;
let add a = match a with &lt;br /&gt;
    (min,max)-&amp;gt; ((min+1),(max+1));;&lt;br /&gt;
&lt;br /&gt;
(* retourne la taille max et la taille min d&#039;un tas *)&lt;br /&gt;
let rec tailleTas tas = match tas with&lt;br /&gt;
    Vide -&amp;gt; (0,0)&lt;br /&gt;
  | Noeud(_,tg,td) -&amp;gt; add (compare (tailleTas tg) (tailleTas td));;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite il suffit d&#039;utiliser cette fonction sur le tas et de comparer l&#039;écart entre la branche la plus courte et la branche la plus longue.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let equilibre tas = match (tailleTas tas) with&lt;br /&gt;
    (min,max) -&amp;gt; (max - min)&amp;lt;2 ;;  (* on calcule la difference entre max et min et on test si elle est inférieur à 2 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 4&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* ajoute un element a un tas *)&lt;br /&gt;
let rec ajouter v tas = match tas with&lt;br /&gt;
     Vide -&amp;gt; Noeud (v,Vide,Vide)&lt;br /&gt;
|    Noeud (tv,tg,td) -&amp;gt; Noeud( min tv v, td, ajouter (max tv v) tg);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
on insère systématiquement dans le tas de droite, mais on permute le tas de gauche et le tas de droite a chaque fois pour &amp;quot;mélanger&amp;quot; le tas et avoir un tas équilibré&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 5&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* ajoute une liste d’elements a un tas *)&lt;br /&gt;
let rec ajList liste tas = match liste with&lt;br /&gt;
     [] -&amp;gt; tas&lt;br /&gt;
|    v::l&#039; -&amp;gt; ajouter v (ajList l&#039; tas);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Il s&#039;agit d&#039;une simple fonction récursive qui parcours la liste et fais appel a la fonction ajouter pour chaque élément de la liste.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;à finir&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 6&#039;&#039;&#039;&lt;br /&gt;
Pour implémenter le tri par tas, nous allons commencer par créer une fonction qui vide un tas et renvoie le contenu de celui-ci dans une liste triée.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* vide un tas et renvoie le contenu du tas dans une liste triée *)&lt;br /&gt;
let rec viderTas tas = match tas with&lt;br /&gt;
     Vide -&amp;gt; []&lt;br /&gt;
|    Noeud (x,_,_) -&amp;gt; (premier tas)::(viderTas (enlever tas)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il nous suffit maintenant de crée un tas avec la liste en utilisant la fonction ajList, et de passer la liste ainsi crée en paramètre a la fonction viderTas. &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* tri la liste passée en paramètre avec la méthode du tri par tas *)&lt;br /&gt;
let triTas lst = viderTas (ajList lst Vide);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;à finir&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Le TD5==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TP4==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==TD6==&lt;/div&gt;</summary>
		<author><name>Laurent corantin</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=INFO401_corr_TD_TP&amp;diff=4170</id>
		<title>INFO401 corr TD TP</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=INFO401_corr_TD_TP&amp;diff=4170"/>
		<updated>2009-05-22T11:54:33Z</updated>

		<summary type="html">&lt;p&gt;Laurent corantin : /* Le TP2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Préliminaires==&lt;br /&gt;
&lt;br /&gt;
Pour afficher correctement dans le wiki, allez voir un peu comment on fait. Vous pouvez regarder par exemple sur le [[INFO401 | wiki du cours]] ou directement sur des articles de [http://fr.wikipedia.org/wiki/Accueil Wikipedia]. La documentation de mediawiki se trouve [http://meta.wikimedia.org/wiki/Aide:Éditeur ici].&lt;br /&gt;
&lt;br /&gt;
Un truc important : pour rentrer du code Caml, il faut mettre les balises &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;...&amp;lt;/source&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; autour de votre code. Allez par exemple voir le début de la section sur [[#Le TD1 et le TP0 | le TD1 et TP0]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vous pouvez aller discuter des corrections dans les sujets de discussions associes...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD1 et le TP0==&lt;br /&gt;
&lt;br /&gt;
Pour vous montrer un exemple de ce que j&#039;attends, voila la correction de la fonction factorielle. (C&#039;était facile...) J&#039;ai volontairement mis beaucoup de commentaires...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;La fonction factorielle (TD1, exercice 2, question 2)&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but est de calculer la fonction &amp;lt;math&amp;gt;!n = 1\times2\times \cdots \times n&amp;lt;/math&amp;gt; par récurrence. La version typée est verbeuse de la fonction correspondante en Caml donne :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* fonction factorielle : c&#039;est la factorielle habituelle des mathématiciens... *)&lt;br /&gt;
let rec fact (n:int) : int =&lt;br /&gt;
  if (n&amp;gt;1)&lt;br /&gt;
  then  n * (fact (n-1))&lt;br /&gt;
  else 1      (* rq : pour que le programme ne boucle pas sur les valeurs négatives, on renvoie 1 dés que n&amp;lt;1 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme la fonction est récursive, il ne faut pas oublier le &amp;lt;tt&amp;gt;rec&amp;lt;/tt&amp;gt; au début de la définition.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On aurait pu faire une autre version, qui fonctionne différemment sur les nombres négatifs :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fact&#039; = function&lt;br /&gt;
   n when (n&amp;gt;0) -&amp;gt; n * fact&#039; (n-1)&lt;br /&gt;
 | n when (n&amp;lt;0) -&amp;gt; n * fact&#039; (n+1)&lt;br /&gt;
 | _ -&amp;gt; 1  (* si n n&#039;est ni plus petit que 0 ni plus grand que 0, n est égal à 0, et on renvoie donc 1 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;ai volontairement mis une version qui contient plusieurs choses que nous n&#039;avons pas encore vues en cours :&lt;br /&gt;
* utilisation de &amp;quot;&amp;lt;tt&amp;gt;function&amp;lt;/tt&amp;gt;&amp;quot; plutôt que &amp;lt;tt&amp;gt;fun&amp;lt;/tt&amp;gt;,&lt;br /&gt;
* le symbole &amp;quot;&amp;lt;tt&amp;gt;|&amp;lt;/tt&amp;gt;&amp;quot;,&lt;br /&gt;
* le mot clé &amp;quot;&amp;lt;tt&amp;gt;when&amp;lt;/tt&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Vous devriez pouvoir comprendre ce que fait la fonction. Sinon, voici une version que vous auriez pu écrire :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fact_bis = fun n -&amp;gt;&lt;br /&gt;
  if (n=0)&lt;br /&gt;
  then 1&lt;br /&gt;
  else begin&lt;br /&gt;
    if (n&amp;gt;0)&lt;br /&gt;
    then n*fact_bis (n-1)&lt;br /&gt;
    else n*fact_bis (n+1)   (* dans ce cas, n est forcement négatif *)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Les fonctions sommes &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il s&#039;agit ici d&#039;écrire la fonction qui va additionner les carrés des entiers de 1 jusqu&#039;à un nombre donné.&lt;br /&gt;
&lt;br /&gt;
Cela donne :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_carre b =&lt;br /&gt;
if (b=0) then 0&lt;br /&gt;
else (b*b) + somme_carre (b-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite on nous demande de calculer la somme des cubes des entiers de 1 jusqu&#039;à un nombre donné. On pourrait faire le même programme en remplaçant b*b par b*b*b, mais on va définir une fonction puissance (car elle n&#039;existe pas d&#039;origine sous Caml), qui nous servira aussi pour la suite... :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec puissance x a =&lt;br /&gt;
if (a = 0) then 1&lt;br /&gt;
else x * puissance x (a-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On doit maintenant calculer la somme des &amp;lt;math&amp;gt;i^i&amp;lt;/math&amp;gt;, i variant de 1 à un nombre donné :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_puissance b =&lt;br /&gt;
if (b=0) then 0&lt;br /&gt;
else (puissance b b) + somme_puissance (b-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut définir une unique fonction qui permettrait de faire toutes ces sommes, celle-ci aura pour argument une fonction quelconque :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_fonction n f = (* f étant une fonction *)&lt;br /&gt;
if (n=0) then f 0&lt;br /&gt;
else f n + somme_fonction (n-1) f;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
cette fonction est de type &amp;quot;&amp;lt;tt&amp;gt;int -&amp;gt; fun -&amp;gt; int&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Nombres pairs et impairs (TP0 Partie 2 Question 2) &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut écrire les fonctions récursives pairs et impairs, qui renvoient vrai si le nombre est pair (respectivement impair) et faux si le nombre est impair (respectivement pair);&lt;br /&gt;
Ici nous devons déclarer simultanément les deux fonctions, car chacune fait appel à l&#039;autre lors de son exécution.&lt;br /&gt;
&lt;br /&gt;
Cela donne :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec pair n =&lt;br /&gt;
  if (n=0) then true&lt;br /&gt;
  else impair (n-1)&lt;br /&gt;
and impair n =&lt;br /&gt;
  if (n=0) then false&lt;br /&gt;
  else  pair (n-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Suite de Fibonacci &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La suite de fibonacci est tel que u&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;=0 u&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;=1 et u&amp;lt;sub&amp;gt;n+2&amp;lt;/sub&amp;gt;=u&amp;lt;sub&amp;gt;n+1&amp;lt;/sub&amp;gt;+u&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib n =&lt;br /&gt;
if (n=0) then 0&lt;br /&gt;
else if (n=1) then 1&lt;br /&gt;
else fib (n-1) + fib (n-2);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La plus grande valeur que l&#039;on peut obtenir sans que cela soit trop long est 24157817, ce qui correspond à fib 37.&lt;br /&gt;
Nous trouvons qu&#039;il faut déjà 88 additions pour calculer fib 10.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Rq :&#039;&#039;&#039; fib de 37 prend effectivement beaucoup de temps. Il faut 39088168 additions avant d&#039;en arriver à bout. Il est possible de faire une version de Fibonacci qui va très vite et qui calcule &amp;lt;tt&amp;gt;fib 37&amp;lt;/tt&amp;gt; en seulement 36 additions...&lt;br /&gt;
: Comment ?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Dragon ! &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;i&amp;gt; Le dragon est une créature mythique, présente dans de nombreuses cultures.&lt;br /&gt;
  On peut déterminer deux grands types de dragons : le dragon occidental et le dragon oriental&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction dragon a pour but de dessiner un dragon, pour cela on utilise une fonction récursive qui admet pour argument le nombre n d&#039;itération de la fonction, et les coordonnées de 2 points. A chaque itération, la fonction calcule pour chaque segment, un nouveau point et le relie ensuite aux deux autres.&lt;br /&gt;
&lt;br /&gt;
On obtient en tout 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; segments entremêlés, qui forment un dragon.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s go !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec dragon (n:int) (a:int) (b:int) (c:int) (d:int) : unit =&lt;br /&gt;
if (n = 0) then (moveto a b ; lineto c d)&lt;br /&gt;
               else begin&lt;br /&gt;
                      let x = (a+c+d-b)/2 in&lt;br /&gt;
                      let y = (b+d+a-c)/2 in&lt;br /&gt;
                      dragon (n-1) a b x y ;&lt;br /&gt;
                      dragon (n-1) c d x y&lt;br /&gt;
                    end ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Rq : &#039;&#039;&#039; votre version du dragon est bien, mais pas très précises. (Je chipote un peu...)  Pour les paramètres (&amp;lt;tt&amp;gt;dragon 11 100 100 400 400&amp;lt;/tt&amp;gt;), de nombreux carrés ne sont pas bien tracés.&lt;br /&gt;
:Comment expliquez-vous cela, et comment pouvez-vous le corriger ?&lt;br /&gt;
&lt;br /&gt;
::Pour améliorer la précision je suggère de passer les coordonnées en type Float. --[[Utilisateur:Nicolas|Nicolas]] 31 janvier 2009 à 11:42 (CET)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD2==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exercice 1 : Tuples&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 4 :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
On définit la fonction curry par:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let curry (f: &#039;a * &#039;b -&amp;gt; &#039;c) : &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;c&lt;br /&gt;
     = fun x y -&amp;gt; f(x,y);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ou encore en simplifiant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let curry f x y = f(x,y);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On définit ensuite la fonction uncurry par:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry (f: &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;c) : &#039;a * &#039;b -&amp;gt; &#039;c&lt;br /&gt;
     = fun x -&amp;gt; f (fst x) (snd x);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ou encore de trois autres manières plus simplifiées:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = fun x -&amp;gt; f (fst x) (snd x);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = fun x -&amp;gt; match x with (a,b) -&amp;gt; f a b;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = function (a,b) -&amp;gt; f a b;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Avantage de la première forme (à plusieurs arguments): Elle permet une application partielle: on peut appliquer cette fonction à une seule partie des arguments.&lt;br /&gt;
&lt;br /&gt;
Inconvénients de la seconde forme (à un argument): &lt;br /&gt;
*il faut faire appel à fst, snd;&lt;br /&gt;
*Caml doit séparer les paires: c&#039;est une perte de temps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 5 :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
D&#039;après la fonction récursive Fibonacci définit par &amp;lt;br /&amp;gt;&lt;br /&gt;
f(0)=0 &amp;lt;br /&amp;gt;&lt;br /&gt;
f(1)=1 &amp;lt;br /&amp;gt;&lt;br /&gt;
f(n+2)=f(n+1)+f(n), &amp;lt;br /&amp;gt;&lt;br /&gt;
comment compter le nombre d&#039;appels récursifs en Caml? &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* la fonction renvoie une valeur de type int*int :&lt;br /&gt;
  - la première composante est la valeur de Fibonacci pour n,&lt;br /&gt;
  - la seconde composante est le nonbre d&#039;appels recursifs effectués *)&lt;br /&gt;
 let rec fib n =&lt;br /&gt;
     if (n&amp;lt;2) then (n,0)&lt;br /&gt;
     else let t = fib (n-1) in&lt;br /&gt;
          let s = fib (n-2) in &lt;br /&gt;
     (fst t + fst s , snd t + snd s + 1)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&#039;&#039;exemple : &#039;&#039;fib 10 = (55, 88) pour exécuter la fonction Fibonacci(10), il y a 88 appels récursifs nécessaires...&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exercice 2 : Listes&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 5 :&#039;&#039;&#039;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
suite à l&#039;étude des fonctions &lt;br /&gt;
*longueur&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec longueur l =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; 0&lt;br /&gt;
     | _::l -&amp;gt; 1 + longueur l&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*applique&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec app f p =&lt;br /&gt;
     match p with &lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
     | a :: p -&amp;gt; f(a) :: app f p&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*concatene&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec cat l1 l2 =&lt;br /&gt;
     match l1 with&lt;br /&gt;
     [] -&amp;gt; l2&lt;br /&gt;
     | a :: l -&amp;gt; a :: (cat l l2)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*renverse,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec renverse l =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
     | a :: l -&amp;gt; (renverse l) @ [a]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
on remarque des similitudes. Ces fonctions ont le même schéma de base. On peut résumer le principe commun dans la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec reduit l o f =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; o&lt;br /&gt;
     | a :: l -&amp;gt; let appel_rec = reduit l o f in&lt;br /&gt;
                 f a appel_rec&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&#039;&#039;NB :&#039;&#039; le type de &amp;lt;tt&amp;gt;reduit&amp;lt;/tt&amp;gt; donné par Caml est : &amp;lt;tt&amp;gt;val reduit : &#039;a list -&amp;gt; &#039;b -&amp;gt; (&#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b) -&amp;gt; &#039;b = &amp;lt;fun&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 6 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
Reprogrammons les fonctions précédentes à partir de la fonction reduit ! &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let longueur l =&lt;br /&gt;
     let f _ r = 1 + r in &lt;br /&gt;
     reduit l 0 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let app g l =&lt;br /&gt;
     let f a r = (g a)::r in&lt;br /&gt;
     reduit l [] f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let cat l1 l2 =&lt;br /&gt;
     let f a r = a :: r in  &lt;br /&gt;
     reduit l1 l2 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut également introduire la fonction directement avec un &amp;lt;tt&amp;gt;fun&amp;lt;/tt&amp;gt; de la maniere suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let renverse l = reduit l [] (fun a r -&amp;gt; r @ [a])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 7 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le type de la fonction reduit est: ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b ) -&amp;gt; &#039;a list &amp;lt;br/&amp;gt;&lt;br /&gt;
Celui de la fonction List.fold_right est: ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b ) -&amp;gt; &#039;a list -&amp;gt; &#039;b -&amp;gt; &#039;b  ;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
l&#039;ordre des arguments de fold_right est le même que l&#039;ordre des arguments de reduit. La fonction fold_right compte juste deux arguments supplémentaires.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 8 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici la fonction fold_left:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let rec fold_left f b l=&lt;br /&gt;
      match l with&lt;br /&gt;
        []-&amp;gt;b&lt;br /&gt;
       |a::l -&amp;gt; fold_left f (f b a) l;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Cette fonction est &#039;&#039;récursive terminale&#039;&#039;, de type ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;a ) -&amp;gt; &#039;a -&amp;gt; &#039;b list -&amp;gt; &#039;a .&lt;br /&gt;
&lt;br /&gt;
==Le TP1 - début==&lt;br /&gt;
&lt;br /&gt;
Le sujet [http://www.lama.univ-savoie.fr/~hyvernat/Enseignement/0809/info401/tp1.pdf programmes récursifs, listes], au format pdf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 1 : Quelques compléments sur les programmes récursifs&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans cette partie, on travaille sur la fonction Fibonacci&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On commence par l&#039;utiliser sous la forme :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib n =&lt;br /&gt;
if n&amp;lt;2&lt;br /&gt;
   then n&lt;br /&gt;
   else fib (n-1) + fib (n-2)&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comprendre ce qu&#039;il se passe, on trace la fonction à l&#039;aide de &amp;quot;#trace&amp;quot; pour fib 5&lt;br /&gt;
&lt;br /&gt;
fib &amp;lt;-- n veut dire que l&#039;on donne la valeur n à la fonction fib&lt;br /&gt;
&lt;br /&gt;
alors que fib --&amp;gt; n veut dire que fib renvoie n&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib 5 ;;&lt;br /&gt;
fib &amp;lt;-- 5&lt;br /&gt;
fib &amp;lt;-- 3&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib &amp;lt;-- 2&lt;br /&gt;
fib &amp;lt;-- 0&lt;br /&gt;
fib --&amp;gt; 0&lt;br /&gt;
...&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib &amp;lt;-- 2&lt;br /&gt;
fib &amp;lt;-- 0&lt;br /&gt;
fib --&amp;gt; 0&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib --&amp;gt; 2&lt;br /&gt;
fib --&amp;gt; 3&lt;br /&gt;
fib --&amp;gt; 5&lt;br /&gt;
- : int = 5&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut remarquer que la fonction calcule plusieurs fois le même fib n.&lt;br /&gt;
Une optimisation consisterait à garder certaines valeurs en mémoire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On écrit fib2 de type &amp;quot;int -&amp;gt; int*int&amp;quot; qui renvoie le valeur de fib n (fst fib2 n) et fib n-1 (snd (fib2 n)) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib2 n = &lt;br /&gt;
if n&amp;lt;2 &lt;br /&gt;
   then (n,n-1)&lt;br /&gt;
   else let t = fib2 (n-1) in&lt;br /&gt;
      (fst(t)+snd(t),fst(t));;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 3&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comparer les fonctions fib et fib2, on les trace pour n=7 :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib 7 ;;&lt;br /&gt;
fib &amp;lt;-- 7&lt;br /&gt;
fib &amp;lt;-- 5&lt;br /&gt;
fib &amp;lt;-- 3&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
...&lt;br /&gt;
fib --&amp;gt; 3&lt;br /&gt;
fib --&amp;gt; 5&lt;br /&gt;
fib --&amp;gt; 8&lt;br /&gt;
fib --&amp;gt; 13&lt;br /&gt;
- : int = 13&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib2 7 ;;&lt;br /&gt;
fib2 &amp;lt;-- 7&lt;br /&gt;
fib2 &amp;lt;-- 6&lt;br /&gt;
fib2 &amp;lt;-- 5&lt;br /&gt;
fib2 &amp;lt;-- 4&lt;br /&gt;
fib2 &amp;lt;-- 3&lt;br /&gt;
fib2 &amp;lt;-- 2&lt;br /&gt;
fib2 &amp;lt;-- 1&lt;br /&gt;
fib2 --&amp;gt; (1, 0)&lt;br /&gt;
fib2 --&amp;gt; (1, 1)&lt;br /&gt;
fib2 --&amp;gt; (2, 1)&lt;br /&gt;
fib2 --&amp;gt; (3, 2)&lt;br /&gt;
fib2 --&amp;gt; (5, 3)&lt;br /&gt;
fib2 --&amp;gt; (8, 5)&lt;br /&gt;
fib2 --&amp;gt; (13, 8)&lt;br /&gt;
- : int * int = (13, 8)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On remarque que fib2 fait 14 calculs alors que fib en 81 pour n=7.&lt;br /&gt;
Afin de retourner uniquement la valeur de fib n on définit une nouvelle fonction, beaucoup plus rapide que fib, &lt;br /&gt;
en prenant le premier élément de la paire constituant fib2 n :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let fib n = fst ( fib2 n ) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 4 ( Bonus )&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On veut créer fib3 de type int-&amp;gt;int-&amp;gt;int-&amp;gt;int tel que :&lt;br /&gt;
&lt;br /&gt;
- son premier argument est l&#039;entier n pour fibonacci de n&lt;br /&gt;
&lt;br /&gt;
- les 2 autres arguments sont des accumulateurs qui permettent de conserver des valeurs successives ( pour i-1 et i )&lt;br /&gt;
&lt;br /&gt;
 --- à venir ---&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 2 : Manipulation des listes&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici quelque fonctions définies en utilisant &amp;lt;tt&amp;gt;List.fold_right&amp;lt;/tt&amp;gt; :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let longueur l = let f a r = 1 + r in List.fold_right f l 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let app f l = let f&#039; a r = ( f a )::r in List.fold_right f&#039; l []&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let concat l1 l2 = let f a r = a::r in List.fold_right l1 l2 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici la fonction reverse telle qu&#039;on l&#039;a écrite dans le TD&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec reverse l = &lt;br /&gt;
  match l with&lt;br /&gt;
  []-&amp;gt;[]&lt;br /&gt;
  |a::l -&amp;gt; (reverse l)@[a] ;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour la comparer avec la fonction &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; de Caml, on va regarder le temps d&#039;exécution sur une très grande liste.&lt;br /&gt;
&lt;br /&gt;
Pour cela, on créé une fonction qui fabrique une liste de n valeurs :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec longueliste  n = &lt;br /&gt;
  if n=0 &lt;br /&gt;
  then []&lt;br /&gt;
  else n::longueliste (n-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut tester les fonctions avec une liste de 10000 éléments.&lt;br /&gt;
&lt;br /&gt;
La fonction &amp;lt;tt&amp;gt;reverse&amp;lt;/tt&amp;gt; met environ 15s alors que &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; s&#039;exécute immédiatement.&lt;br /&gt;
&lt;br /&gt;
Cela montre donc que &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; est bien plus efficace que &amp;lt;tt&amp;gt;reverse&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::En fait, reverse fait ( n + n-1 + n-2 + ... + 1 ) opérations à chaque fois (il met le premier élément au bout de la liste et ainsi de suite) , soit au total &amp;lt;math&amp;gt;n*(n+1)/2 \sim n^2&amp;lt;/math&amp;gt; opérations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; utilise la fonction suivante :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec rev_append l1 l2 =&lt;br /&gt;
  match l1 with&lt;br /&gt;
    [] -&amp;gt; l2&lt;br /&gt;
  | a::l -&amp;gt; rev_append l (a::l2);;&lt;br /&gt;
&lt;br /&gt;
let rec rev l = rev_append l [];;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Elle fait donc environ &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; opérations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 3 : Deux algorithmes de tri pour les listes&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On programme une fonction d&#039;insertion qui permet d&#039;insérer un élément à sa place&lt;br /&gt;
dans une liste triée.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insertion n l =&lt;br /&gt;
  match l with&lt;br /&gt;
    [] -&amp;gt; [n]&lt;br /&gt;
  | a::l&#039; -&amp;gt; if n&amp;lt;=a&lt;br /&gt;
             then n::l&lt;br /&gt;
             else a::(insertion n l&#039;) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On programme ensuite le tri par insertion.&lt;br /&gt;
&lt;br /&gt;
Le tri par insertion fonctionne de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
- la liste vide est triée,&lt;br /&gt;
&lt;br /&gt;
- pour trier la liste &amp;quot;&amp;lt;tt&amp;gt;a::l&amp;lt;/tt&amp;gt;&amp;quot;, on commence par trier (récursivement) la liste &amp;lt;tt&amp;gt;l&amp;lt;/tt&amp;gt;, puis on insère&lt;br /&gt;
l&#039;élément &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; dans le résultat.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec tri_insertion l =&lt;br /&gt;
 match l with&lt;br /&gt;
    [] -&amp;gt; []&lt;br /&gt;
  | a::l&#039; -&amp;gt; insertion a (tri_insertion l&#039;) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ou plus simplement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let tri l = List.fold.right insertion l [] ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 3&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Maintenant, on programme une fonction fusionne qui permet de fusionner deux listes triées en une seule liste triée.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionne l1 l2 =&lt;br /&gt;
  match l1 with &lt;br /&gt;
     [] -&amp;gt; l2&lt;br /&gt;
   | a::l&#039; -&amp;gt; begin&lt;br /&gt;
                match l2 with&lt;br /&gt;
                   [] -&amp;gt; l1&lt;br /&gt;
                 | b::l&#039;&#039; -&amp;gt; if a&amp;lt;=b then ( a::fusionne l&#039; l2 ) &lt;br /&gt;
                                     else ( b::fusionne l1 l&#039;&#039;) &lt;br /&gt;
&lt;br /&gt;
              end;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour éviter d&#039;imbriquer des &amp;quot;match&amp;quot;, on peut aussi filtrer directement la paire &amp;lt;tt&amp;gt;(l1,l2)&amp;lt;/tt&amp;gt; et regrouper les cas d&#039;un des listes vides ensemble : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionnebis l1 l2 =&lt;br /&gt;
  match l1,l2 with&lt;br /&gt;
      [],l | l,[]  -&amp;gt;  l&lt;br /&gt;
    | (a::l&#039;, b::l2&#039;)  -&amp;gt; &lt;br /&gt;
        if a &amp;lt;= b&lt;br /&gt;
        then a::(fusionnebis l&#039; l2)&lt;br /&gt;
        else b::(fusionnebis l1 l2&#039;)  ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 4&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis une fonction sépare qui permet de séparer une liste quelconque en&lt;br /&gt;
deux listes de taille équivalente&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec separe l =&lt;br /&gt;
  match l with&lt;br /&gt;
     [] -&amp;gt; ([],[])&lt;br /&gt;
   | [a] -&amp;gt; ([a],[])&lt;br /&gt;
   | a::b::l&#039; -&amp;gt; let t=separe l&#039; in (a::(fst t),b::(snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 5&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On doit maintenant programmer un deuxième type de tri : le tri par fusion.&lt;br /&gt;
&lt;br /&gt;
Le tri fusion fonctionne de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
- la liste vide est triée,&lt;br /&gt;
&lt;br /&gt;
- pour trier une liste non-vide, on sépare la liste en deux parties de longueur égale (à un&lt;br /&gt;
élément prêt), on trie (récursivement) ces deux listes, puis on fusionne les deux résultats.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec tri_fusion l =  &lt;br /&gt;
  match l with&lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
   | [a] -&amp;gt; [a]&lt;br /&gt;
   | _ -&amp;gt; let t=separe l in&lt;br /&gt;
          fusionne (tri_fusion (fst t)) (tri_fusion (snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 6&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comparer l&#039;efficacité des deux fonctions de tri, on utilise la même méthode que précédemment : &lt;br /&gt;
&lt;br /&gt;
On créé a l&#039;aide d&#039;un fonction une liste aléatoire de 10000 éléments, les éléments étant non triés.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let liste_aleatoire n =&lt;br /&gt;
  let rec aux n max = &lt;br /&gt;
    if n=0&lt;br /&gt;
    then []&lt;br /&gt;
    else (Random.int max)::aux (n-1) max&lt;br /&gt;
  in&lt;br /&gt;
  aux n n ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite on trie cette liste avec les deux fonctions.&lt;br /&gt;
&lt;br /&gt;
Le tri_fusion renvoie instantanément une liste de 10000 éléments aléatoires triés. &lt;br /&gt;
&lt;br /&gt;
Le tri insertion, quant à lui, prend plus d&#039;une dizaine de secondes.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;Remarque :&#039;&#039; cela vient du fait que le tri fusion divise la taille de la liste par deux à chaque étape, alors que le tri par insertion soustrait un élément à chaque étape.&lt;br /&gt;
: On peut montrer que le temps de calcul pour le tri fusion est proportionnel à &amp;lt;math&amp;gt;n \log(n)&amp;lt;/math&amp;gt;, ce qui est très petit par rapport à &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt; (temps d&#039;execution moyen du tri par insertion) quand &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; est grand.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 7&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On souhaite trier une liste selon la hauteur des points c&#039;est-à-dire selon le deuxième élément de la paire de flottants.&lt;br /&gt;
Pour cela, il faudrait faire un tri fusion sur le 2eme élément de la paire représentant les points&lt;br /&gt;
tout en sauvegardant le 1er élément...&lt;br /&gt;
&lt;br /&gt;
On peut créer une fonction de tri par fusion générale, qui prend comme paramètre une autre fonction (qui sert à vérifier la comparaison de 2 éléments et rend true ou false) afin de choisir le tri que l&#039;on veut ( décroissant, croissant ... ) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionne comp l1 l2 =&lt;br /&gt;
 match (l1,l2) with&lt;br /&gt;
    ([],_) -&amp;gt; l2&lt;br /&gt;
  | (_,[]) -&amp;gt; l1&lt;br /&gt;
  | (a::l&#039;, b::l2&#039;) -&amp;gt; &lt;br /&gt;
     if (comp a b)&lt;br /&gt;
     then a::(fusionne l&#039; l2)&lt;br /&gt;
     else b::(fusionne l1 l2&#039;);;&lt;br /&gt;
&lt;br /&gt;
let rec tri_fusion comp l =  &lt;br /&gt;
 match l with&lt;br /&gt;
    [] -&amp;gt; []&lt;br /&gt;
  | [a] -&amp;gt; [a]&lt;br /&gt;
  | _ -&amp;gt; let t=separe l in&lt;br /&gt;
         fusionne comp (tri_fusion comp (fst t)) (tri_fusion comp (snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il suffit alors a l&#039;utilisateur de définir la fonction de comparaison pour ensuite faire appel à &amp;lt;tt&amp;gt;tri_fusion&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Par exemple, pour trier dans un ordre décroissant :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let dec a n  = if a&amp;gt;=n then true&lt;br /&gt;
else false ;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
ou même plus simplement&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let dec = (&amp;gt;=) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour trier une liste de paires, il faut créer une fonction qui compare les seconds membres ;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let paire a n  = (snd a) &amp;lt;= (snd n)  ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ici, les paires seront triées selon le second membre dans l&#039;ordre croissant.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 8 ( Bonus )&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un algorithme de tri est dit stable quand il ne modifie pas l&#039;ordre relatifs des éléments &amp;quot;égaux&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Par exemple, on tri par ordre croissant du premier membre une liste de paires de float : [ ( 5 , 3 ) ; ( -2 , 8 ) ; ( -2 , 2 ) ; ( 5 , 8 ) ; ( 5 , -8 ) ]  &lt;br /&gt;
&lt;br /&gt;
non stable : &amp;lt;tt&amp;gt;[(-2, 2); (-2, 8); (5, -8); (5, 8); (5, 3)]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
stable : &amp;lt;tt&amp;gt;[(-2, 8); (-2, 2); (5, 3); (5, 8); (5, -8)]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour qu&#039;un tri soit stable, la comparaison de deux éléments doit comprendre aussi le &amp;quot;=&amp;quot;, comme c&#039;est le cas pour les fonctions paire et dec.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD3==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Exercice 1 : les arbres binaires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt; Question 1 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type &#039;a arbre = Vide | Noeud of &#039;a*&#039;a arbre*&#039;a arbre ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 2 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
let rec taille a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; 1 + (taille g) + (taille d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction taille compte le nombre de noeuds que contient un arbre.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 3 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec applique f a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; Vide&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; Noeud(f e,applique f g,applique f d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction applique est équivalente à la fonction List.map&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 4 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec poids (f : &#039;a -&amp;gt; int) a = &lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; (f e) + (poids f g) + (poids f d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 5 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec reduit a o f =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; let x = reduit g o f in&lt;br /&gt;
       			let y = reduit d o f in&lt;br /&gt;
                        f e x y ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction reduit est equivalente à la fonction List.fold_right pour le type des arbres.&lt;br /&gt;
&lt;br /&gt;
Réécriture de taille et poids :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec taille a = reduit a 0 (fun e x y -&amp;gt; 1 + x + y) ;;&lt;br /&gt;
let rec poids f a = reduit a 0 (fun e x y -&amp;gt; (f e) + (f x) + (f y)) ;; (*?????*)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 6 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec collecte a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; []&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; e::(collecte g)@(collecte d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction collecte récupère tous les éléments de l&#039;arbre et les renvoie sous forme d&#039;une liste.&lt;br /&gt;
&lt;br /&gt;
Avec la fonction reduit :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec collecte a = reduit a [] (fun e x y -&amp;gt; e::x@y) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 7 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec feuilles a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; []&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; if (g=Vide &amp;amp;&amp;amp; d=Vide) then [e]&lt;br /&gt;
       			else (feuilles g)@(feuilles d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Avec reduit :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec feuilles a = reduit a [] (fun e x y -&amp;gt; if (x=[] &amp;amp;&amp;amp; y=[]) then [e]&lt;br /&gt;
					       else x@y) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Exercice 2 : la tortue &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt; Question 1 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type action = Forward of int | Left of int | SetPos of int*int | SetHeading of int | PenUp | Pendown ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 2 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
let rec ecrit (l:action list) (pen:bool) : bool =&lt;br /&gt;
   match l with&lt;br /&gt;
    	[] -&amp;gt; false&lt;br /&gt;
       |(Forward d)::l -&amp;gt; if (d=0 || pen=false) then ecrit l pen&lt;br /&gt;
                          else true &lt;br /&gt;
       |PenUp::l -&amp;gt; ecrit l false&lt;br /&gt;
       |PenDown::l -&amp;gt; ecrit l true&lt;br /&gt;
       | _ -&amp;gt; ecrit l pen ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction ecrit renvoie true si la tortue écrit qqch ou false sinon.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 3 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec pos (x:int) (y:int) (a:int) (l:action list) : ((int*int)int) =&lt;br /&gt;
   match l with&lt;br /&gt;
    	[] -&amp;gt; ((x,y),a)&lt;br /&gt;
       |PenUp::l |Pendown::l -&amp;gt; pos x y a l&lt;br /&gt;
       |(Left b)::l -&amp;gt; pos x y (a+b) l&lt;br /&gt;
       |(SetPos(x&#039;,y&#039;))::l -&amp;gt; pos x&#039; y&#039; a l&lt;br /&gt;
       |(SetHeading b)::l -&amp;gt; pos x y b l &lt;br /&gt;
       |(Forward d)::l -&amp;gt; pos (x+(sin a)*d) (y+(cos a)*d) a l ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 5 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type action = Forward of int | SetPos of int*int | SetHeading of int | Left of int | PenUp | Pendown | Repeat of int*action list ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD4==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 1 : Petits exercices combinatoires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On commence par créer une fonction intermédiaire.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supp&#039; x l =&lt;br /&gt;
   match l with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |b::f&#039;-&amp;gt; if (x=b) then supp&#039; x l&#039;&lt;br /&gt;
                        else b::supp&#039; x f&#039;;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supp l =&lt;br /&gt;
   match l with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |a::l&#039;-&amp;gt; a::supp supp&#039; a l&#039;;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 2 : Dictionnaires &amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Un dictionnaire est une liste de paires&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Question 2 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insere c v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[(c,v)]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (c=c&#039;) then (c&#039;,v&#039;)::(insere c v d)&lt;br /&gt;
                               else (c,v)::d ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supprime c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (c=c&#039;) then d&lt;br /&gt;
                               else (c&#039;,v&#039;)::(supprime c d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec existe_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; false&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; (c=c&#039;) || existe_cle c d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec existe_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; false&lt;br /&gt;
      |(_,v&#039;)::d -&amp;gt; if (v=v&#039;) then true&lt;br /&gt;
                              else existe_val v d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec recherche_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; None&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; if (c=c&#039;) then Some c&#039;&lt;br /&gt;
                              else recherche_cle c d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* liste des valeurs de c par on peut avoir plusieurs cases, et donc plusieurs clés, avec une même valeur *)&lt;br /&gt;
let rec recherche_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (v=v&#039;) then c&#039;::(recherche_val v d)&lt;br /&gt;
                              else recherche_val v d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Liste des clés *)&lt;br /&gt;
let rec liste_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; []&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; c&#039;::(liste_cle c d);;&lt;br /&gt;
&lt;br /&gt;
(* Liste des valeurs *)&lt;br /&gt;
let rec liste_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(_,v&#039;)::d -&amp;gt; v&#039;::(liste_val v d);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut également utiliser des fonctions existantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Liste des clés *)&lt;br /&gt;
let liste_cle d = List.map fst;;&lt;br /&gt;
&lt;br /&gt;
(* Liste des valeurs, attention aux doublons! *)&lt;br /&gt;
let liste_val d = suppr_doublons(List.map snd);;&lt;br /&gt;
  &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 4 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec zip l1 l2&lt;br /&gt;
   match l1 l2 with&lt;br /&gt;
      [].[]-&amp;gt;[]&lt;br /&gt;
      |c::lc, v::lv -&amp;gt; (c,v)::(zip lc lv)&lt;br /&gt;
      |_,_ -&amp;gt; [];;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 5 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On aurait pu utiliser une liste triée : si par exemple on cherche 12 et qu&#039;on en est à 14 dans la liste, on sait que 12 n&#039;y est pas. PB : ceci n&#039;empêche pas d&#039;aller à la fin de la liste si la valeur ou la clé recherchée est grande ... &amp;lt;br/&amp;gt;&lt;br /&gt;
Une recherche dichotomique est inefficace sur les listes ... &amp;lt;br/&amp;gt;&lt;br /&gt;
   =&amp;gt; dans la bibliothèque hash table de Caml, il existe un List.zip&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 3 : Arbres binaires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Question 1 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
La profondeur d&#039;un arbre binaire correspond au nombre d&#039;étage : on regarde à partir de la première racine et des sous arbres, on calcule la profondeur à gauche et la profondeur à droite, on prend la plus grande et on y ajoute 1. &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec profondeur a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; 0&lt;br /&gt;
      |Noeud(_,g,d) -&amp;gt; 1 + max(profondeurg) (profondeurd);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 2 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec equilibre a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; true&lt;br /&gt;
      |Noeud(_,g,d) -&amp;gt; if (profondeur g)=(profondeur d) || (profondeur g)=(profondeur d +1) || (profondeur g +1)=(profondeur d)&lt;br /&gt;
                          then (equilibre d)&amp;amp;&amp;amp;(equilibre g)&lt;br /&gt;
                          else false;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec present e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; false&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; e&#039;=e || present e g || present e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 4 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec present e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; false&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; if (e&#039;=e) then true&lt;br /&gt;
                                  else  if (e&amp;lt;e&#039;) then present e g&lt;br /&gt;
                                                  else present e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 5 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insere e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; e&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; if (e&amp;lt;e&#039;) then insere e g&lt;br /&gt;
                                  else insere e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Le TP2==&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt;Partie 1&amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
QUESTION 1 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction suivante permet de calculer les ensemble de nombre. Elle est réalisé à l&#039;aide d&#039;une concaténation de la liste précédente avec la liste modifier ainsi que List.map.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
open List&lt;br /&gt;
&lt;br /&gt;
let rec sous_ensemble n=&lt;br /&gt;
    if n=0&lt;br /&gt;
    then &lt;br /&gt;
      [[]]&lt;br /&gt;
    else&lt;br /&gt;
      let liste = sous_ensemble (n-1) in (List.map (fun l-&amp;gt;n::l) liste) @ liste&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 2 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction supprime doublon est réalisé tout d&#039;abord en triant la liste puis en regardant si deux éléments concécutif sont les mêmes, si oui on en supprime un.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec lstTrier liste=&lt;br /&gt;
  match liste with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
    | [a]-&amp;gt;liste&lt;br /&gt;
    | a::b::liste-&amp;gt;if a=b then lstTrier (a::liste)&lt;br /&gt;
                          else a::lstTrier (b::liste)&lt;br /&gt;
&lt;br /&gt;
let supprime_doublon lst=&lt;br /&gt;
 lstTrier (List.sort (-) lst)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt;Partie 2&amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
QUESTION 1 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction taille calcul la taille d&#039;un arbre, on incrémente un compteur dès que l&#039;on rencontre un noeud. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec taille (arbre:&#039;a arbre)=&lt;br /&gt;
  match arbre  with&lt;br /&gt;
    Vide     -&amp;gt; 0&lt;br /&gt;
  | Noeud(_,a,b) -&amp;gt; 1 + taille a+taille b&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
la fonction applique permet d&#039;appliquer une fonction a tous les éléments d&#039;un arbre.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec applique (fc:&#039;a-&amp;gt;&#039;b) arbre=&lt;br /&gt;
  match arbre with&lt;br /&gt;
    Vide-&amp;gt;Vide&lt;br /&gt;
  | Noeud(a,b,c)-&amp;gt;Noeud (fc a,applique fc b,applique fc c )&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
la fonction fold renvoie le contenu des feuilles composant l&#039;arbre.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec fold (f:&#039;a-&amp;gt;&#039;b-&amp;gt;&#039;b-&amp;gt;&#039;b) arbre n=&lt;br /&gt;
  match arbre with&lt;br /&gt;
    Vide-&amp;gt;n&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;f a(fold f b n) (fold f c n)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 2 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction feuille crée une liste à partir des éléments retourné par la fonction fold.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec feuilles (f:&#039;a arbre-&amp;gt;&#039;a list) arbre=&lt;br /&gt;
  fold (fun a b c-&amp;gt; if(b=[])&amp;amp;&amp;amp;(c=[]) &lt;br /&gt;
     then [a] &lt;br /&gt;
     else (b@c)) arbre[]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 3 :&amp;lt;br/&amp;gt;&lt;br /&gt;
cette fonction permet de créer un arbre à partir d&#039;une liste, elle regarde la taille des branches afin de pouvoir inserer les éléments de façon à avoir le moins de noeuds possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec insert arbre aInsert=&lt;br /&gt;
  match arbre with&lt;br /&gt;
      Vide-&amp;gt;Noeud (aInsert,Vide,Vide)&lt;br /&gt;
    | Noeud (a,b,c)-&amp;gt;if (taille b &amp;lt; taille c) then Noeud(a,(insert b aInsert),c) else Noeud(a,b,(insert c aInsert))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
let rec construit_arbre_int liste arbre=&lt;br /&gt;
  match liste with &lt;br /&gt;
      [a]-&amp;gt;insert arbre a&lt;br /&gt;
    | a::liste-&amp;gt;construit_arbre_int liste (insert arbre a)&lt;br /&gt;
&lt;br /&gt;
let construit_arbre liste=&lt;br /&gt;
  construit_arbre_int liste Vide&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 4 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction se divise en deux partie : l&#039;une permet d&#039;obtenir la taille minimal d&#039;une branche et l&#039;autre la taille maximal, la fonction affiche ensuite les résultats.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec calcMax arbre compt=&lt;br /&gt;
match arbre with&lt;br /&gt;
    Vide-&amp;gt;compt&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;if (taille b &amp;gt; taille c) then calcMax b compt+1 else calcMax c compt+1&lt;br /&gt;
&lt;br /&gt;
let rec calcMin arbre compt=&lt;br /&gt;
match arbre with&lt;br /&gt;
    Vide-&amp;gt;compt&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;if (taille b &amp;lt; taille c) then calcMax b compt+1 else calcMax c compt+1&lt;br /&gt;
&lt;br /&gt;
let profondeurs arbre=&lt;br /&gt;
  (calcMax arbre 0 , calcMin arbre 0)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 5 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction tailleR est la fonction tille pour les arbres binaires.&amp;lt;br/&amp;gt;&lt;br /&gt;
nous pouvons remarquer que la fonction applique pourrait rendre un arbre binaire faux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
type &#039;a abr = Vide | Noeud of &#039;a abr * &#039;a* &#039;a abr&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
let rec tailleR abr=&lt;br /&gt;
  match abr with&lt;br /&gt;
    Vide     -&amp;gt; 0&lt;br /&gt;
  | Noeud(a,_,b) -&amp;gt; 1 + tailleR a+tailleR b&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 6 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction ajoute permet d&#039;ajouter une donnée en conservant un arbre binaire.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec ajoute arbre aInsert=&lt;br /&gt;
  match arbre with&lt;br /&gt;
      Vide-&amp;gt;Noeud (Vide,aInsert,Vide)&lt;br /&gt;
    | Noeud (a,b,c)-&amp;gt;if aInsert&amp;lt;b then Noeud((ajoute a aInsert),b,c) else Noeud(a,b,(ajoute c aInsert))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
QUESTION 7:&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction supp utilise aissi la fonction ajoute afin de conserver un arbre binaire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec supp arbre aSupp=&lt;br /&gt;
  match arbre with&lt;br /&gt;
      Vide-&amp;gt;Vide&lt;br /&gt;
    | Noeud (a,b,c)-&amp;gt;&lt;br /&gt;
	if (aSupp=b) &lt;br /&gt;
	then &lt;br /&gt;
	  if (a=Vide&amp;amp;&amp;amp;c=Vide)&lt;br /&gt;
	  then Vide&lt;br /&gt;
	  else&lt;br /&gt;
	    if (a=Vide&amp;amp;&amp;amp;c!=Vide)&lt;br /&gt;
	    then supp c aSupp&lt;br /&gt;
	    else&lt;br /&gt;
	      if (a!=Vide&amp;amp;&amp;amp;c=Vide)&lt;br /&gt;
	      then supp a aSupp&lt;br /&gt;
	      else&lt;br /&gt;
		ajouteArbre c a&lt;br /&gt;
	else Noeud((supp a aSupp),b,(supp c aSupp))&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 8:&amp;lt;br/&amp;gt;&lt;br /&gt;
afin de verifier si un arbre est binaire on effectue deux match simultané a tous les noeuds rencontrés en parcourant l&#039;arbre.&lt;br /&gt;
&amp;lt;source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec verifabr arbre=&lt;br /&gt;
match arbre with&lt;br /&gt;
    Vide-&amp;gt;true&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;&lt;br /&gt;
	  match a with&lt;br /&gt;
	      Vide-&amp;gt;true&lt;br /&gt;
	    | Noeud (a2,b2,c2)-&amp;gt;if b2&amp;lt;b then verifabr a else false&lt;br /&gt;
	&amp;amp;&amp;amp;&lt;br /&gt;
	  match c with&lt;br /&gt;
	      Vide-&amp;gt;true&lt;br /&gt;
	    | Noeud (a3,b3,c3)-&amp;gt;if b3&amp;gt;b then verifabr c else false&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Contrôle continu 1==&lt;br /&gt;
&#039;&#039;&#039;Partie 2&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
cette fonction s&#039;applique a tout les elements d&#039;une liste&lt;br /&gt;
&lt;br /&gt;
  &#039;&#039;&#039;let rec pam0 a l &#039;&#039;&#039;= &lt;br /&gt;
  match l with []-&amp;gt;[]&lt;br /&gt;
  |f::l-&amp;gt;(f a)::(pam0 a l);;                                                   &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
la meme fonction mais cette fois on utilise Fold_right&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039; let pam a l&#039;&#039;&#039; = List.fold_right(fun f t -&amp;gt;(f a)::t)l [];;&lt;br /&gt;
&lt;br /&gt;
ou encore la version avec List.map,elle a le meme type que pam&lt;br /&gt;
  &#039;&#039;&#039;let pam1 a&#039;&#039;&#039; = List.map(fun f-&amp;gt;f a);;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 2&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
   &#039;&#039;&#039;let rec seq i n&#039;&#039;&#039; = if n&amp;lt;i then []&lt;br /&gt;
   else (seq i(n-1))@[n];;&lt;br /&gt;
&lt;br /&gt;
   seq est du type:int-&amp;gt;int-&amp;gt;int list,cette fonction créee une liste&lt;br /&gt;
d&#039;entier consecutifs et concatène un element en fin de liste par exemple::&lt;br /&gt;
seq 5 14;; &lt;br /&gt;
   &#039;&#039;&#039;-:int list&#039;&#039;&#039; = [5;6;7;8;9;10;11;12;13;14]   &lt;br /&gt;
mais a partir de 5 chriffres l&#039;execution  met plus d&#039;une demi seconde &lt;br /&gt;
&lt;br /&gt;
essayons la version simple&lt;br /&gt;
   &#039;&#039;&#039;let rec seq1 i n&#039;&#039;&#039; = if n&amp;lt;i then [] else i::(seq(i+1)n);;&lt;br /&gt;
&lt;br /&gt;
la version recursive terminale avec un accumulateur nous permettons d&#039;avoir&lt;br /&gt;
une execution rapide de la fonction&lt;br /&gt;
 &lt;br /&gt;
    &#039;&#039;&#039;let seq2 i n&#039;&#039;&#039; =&lt;br /&gt;
   &#039;&#039;&#039; let rec aux i n acc &#039;&#039;&#039;=&lt;br /&gt;
          if n&amp;lt;i then acc &lt;br /&gt;
          else aux i(n-1) (n::acc)&lt;br /&gt;
     in &lt;br /&gt;
     aux i n [];; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Partie 3&#039;&#039;&#039;&lt;br /&gt;
suite de robinson&lt;br /&gt;
ecrivons d&#039;abord une iteration qui nous permet de repéter&lt;br /&gt;
l&#039;action sur la fonction&lt;br /&gt;
    &#039;&#039;&#039;let rec iter f n x&#039;&#039;&#039; = if n=0 then x else iter f(n-1)(f x);;&lt;br /&gt;
ensuite la fonction suivant pour passer d&#039;un terme a l&#039;autre&lt;br /&gt;
   &#039;&#039;&#039; let suivant u &#039;&#039;&#039;= &lt;br /&gt;
    (*nous avons aussi la fonction aux permettant de compter le nombre de fois&lt;br /&gt;
             ou d apparait dans n*)&lt;br /&gt;
   &#039;&#039;&#039; let rec aux u n d &#039;&#039;&#039;= match u with []-&amp;gt;n::d::[]&lt;br /&gt;
    |a::u when a=d -&amp;gt; aux u (n+1) d&lt;br /&gt;
    |a::u-&amp;gt;n::d::(aux u 1 a)&lt;br /&gt;
    in &lt;br /&gt;
    &#039;&#039;&#039;let u &#039;&#039;&#039;= List.sort(fun x y-&amp;gt;y-x)u (*et la fonction u qui nous permet de trier par ordre &lt;br /&gt;
    decroissant en utilisant List.sort*)&lt;br /&gt;
    in &lt;br /&gt;
    match u with []-&amp;gt;[]&lt;br /&gt;
    |a::u-&amp;gt; aux u 1 a;;&lt;br /&gt;
&lt;br /&gt;
==Le TP3==&lt;br /&gt;
&#039;&#039;&#039;Partie 1&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 1&#039;&#039;&#039;&lt;br /&gt;
Déclaration du type pour les tas ( &#039;a tas )&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;type &#039;a tas = Vide | Noeud of &#039;a * &#039;a tas * &#039;a tas ;;&amp;lt;/source&amp;gt;&lt;br /&gt;
La fonction pour tester si un élement de type &#039;a tas est effectivement un tas : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;let rec test tas vPrec = match tas with&lt;br /&gt;
    Noeud(v,t1,t2) -&amp;gt; if v &amp;gt;= vPrec &lt;br /&gt;
                        then ((test t1 v)&amp;amp;(test t2 v))&lt;br /&gt;
                        else false&lt;br /&gt;
  |Vide -&amp;gt; true&lt;br /&gt;
&lt;br /&gt;
let testTas tas = match tas with  &lt;br /&gt;
   Noeud(v,_,_) -&amp;gt; test tas v &lt;br /&gt;
  |Vide -&amp;gt; true &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 2&#039;&#039;&#039;&lt;br /&gt;
Pour cette question nous allons écrire 3 fonctions.&lt;br /&gt;
La première a pour but de supprimer le premier élément du tas (donc le plus petit), la seconde a pour but de retourner la valeur du premier élément du tas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;(*Enleve le premier element du tas&lt;br /&gt;
&lt;br /&gt;
 Explication du nom de variables&lt;br /&gt;
   tgv -&amp;gt; tas gauche valeur ( valeur du tas de gauche)&lt;br /&gt;
   tgg -&amp;gt; tas gauche gauche ( le tas gauche du tas gauche)&lt;br /&gt;
   tgd -&amp;gt; tas gauche droit ( le tas droit du tas gauche)&lt;br /&gt;
*)&lt;br /&gt;
let rec enlever tas = match tas with&lt;br /&gt;
     Vide -&amp;gt; Vide                             (* Si le tas est vide on retourne le tas Vide *)&lt;br /&gt;
|    Noeud (v,Vide,td) -&amp;gt; td                  (* Si le tas gauche est Vide on retourne le tas droit *) &lt;br /&gt;
|    Noeud (v,tg,Vide) -&amp;gt; tg                  (* Si le tas droit est Vide on retourne le tas gauche *)&lt;br /&gt;
|    Noeud (v, (Noeud (tgv,tgg,tgd) as tg),   &lt;br /&gt;
               (Noeud (tdv,tdg,tdd) as td))   (* Si aucun des deux tas est vide *)&lt;br /&gt;
     -&amp;gt; if tgv &amp;lt; tdv&lt;br /&gt;
       then Noeud (tgv, enlever tg, td)   &lt;br /&gt;
       else Noeud (tdv, tg, enlever td);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Renvoie la valeur du premier element du tas *)&lt;br /&gt;
let premier tas = match tas with &lt;br /&gt;
    Vide -&amp;gt; raise Tas_Vide&lt;br /&gt;
  | Noeud(v,_,_) -&amp;gt; v ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On combine ces deux fonctions pour crée la fonction demandée.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let min_tas tas = ((premier tas),(enlever tas));;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 3&#039;&#039;&#039;&lt;br /&gt;
Nous allons crée un fonction qui va calculer la taille de la plus petite branche du tas et de la plus grande branche du tas.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* compare les taille max et les taille min des tas calculé par la fonction tailleTas *)&lt;br /&gt;
let compare a b = match (a,b) with &lt;br /&gt;
    ((amin,amax),(bmin,bmax)) -&amp;gt; ((min amin bmin),(max amax bmax));;&lt;br /&gt;
&lt;br /&gt;
(* ajoute 1 a la taille du tas *)&lt;br /&gt;
let add a = match a with &lt;br /&gt;
    (min,max)-&amp;gt; ((min+1),(max+1));;&lt;br /&gt;
&lt;br /&gt;
(* retourne la taille max et la taille min d&#039;un tas *)&lt;br /&gt;
let rec tailleTas tas = match tas with&lt;br /&gt;
    Vide -&amp;gt; (0,0)&lt;br /&gt;
  | Noeud(_,tg,td) -&amp;gt; add (compare (tailleTas tg) (tailleTas td));;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite il suffit d&#039;utiliser cette fonction sur le tas et de comparer l&#039;écart entre la branche la plus courte et la branche la plus longue.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let equilibre tas = match (tailleTas tas) with&lt;br /&gt;
    (min,max) -&amp;gt; (max - min)&amp;lt;2 ;;  (* on calcule la difference entre max et min et on test si elle est inférieur à 2 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 4&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* ajoute un element a un tas *)&lt;br /&gt;
let rec ajouter v tas = match tas with&lt;br /&gt;
     Vide -&amp;gt; Noeud (v,Vide,Vide)&lt;br /&gt;
|    Noeud (tv,tg,td) -&amp;gt; Noeud( min tv v, td, ajouter (max tv v) tg);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
on insère systématiquement dans le tas de droite, mais on permute le tas de gauche et le tas de droite a chaque fois pour &amp;quot;mélanger&amp;quot; le tas et avoir un tas équilibré&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 5&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* ajoute une liste d’elements a un tas *)&lt;br /&gt;
let rec ajList liste tas = match liste with&lt;br /&gt;
     [] -&amp;gt; tas&lt;br /&gt;
|    v::l&#039; -&amp;gt; ajouter v (ajList l&#039; tas);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Il s&#039;agit d&#039;une simple fonction récursive qui parcours la liste et fais appel a la fonction ajouter pour chaque élément de la liste.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;à finir&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Queston 6&#039;&#039;&#039;&lt;br /&gt;
Pour implémenter le tri par tas, nous allons commencer par créer une fonction qui vide un tas et renvoie le contenu de celui-ci dans une liste triée.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* vide un tas et renvoie le contenu du tas dans une liste triée *)&lt;br /&gt;
let rec viderTas tas = match tas with&lt;br /&gt;
     Vide -&amp;gt; []&lt;br /&gt;
|    Noeud (x,_,_) -&amp;gt; (premier tas)::(viderTas (enlever tas)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il nous suffit maintenant de crée un tas avec la liste en utilisant la fonction ajList, et de passer la liste ainsi crée en paramètre a la fonction viderTas. &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* tri la liste passée en paramètre avec la méthode du tri par tas *)&lt;br /&gt;
let triTas lst = viderTas (ajList lst Vide);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;à finir&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
==Le TD5==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TP4==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==TD6==&lt;/div&gt;</summary>
		<author><name>Laurent corantin</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=INFO401_corr_TD_TP&amp;diff=4148</id>
		<title>INFO401 corr TD TP</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=INFO401_corr_TD_TP&amp;diff=4148"/>
		<updated>2009-05-03T11:38:00Z</updated>

		<summary type="html">&lt;p&gt;Laurent corantin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Préliminaires==&lt;br /&gt;
&lt;br /&gt;
Pour afficher correctement dans le wiki, allez voir un peu comment on fait. Vous pouvez regarder par exemple sur le [[INFO401 | wiki du cours]] ou directement sur des articles de [http://fr.wikipedia.org/wiki/Accueil Wikipedia]. La documentation de mediawiki se trouve [http://meta.wikimedia.org/wiki/Aide:Éditeur ici].&lt;br /&gt;
&lt;br /&gt;
Un truc important : pour rentrer du code Caml, il faut mettre les balises &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;...&amp;lt;/source&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; autour de votre code. Allez par exemple voir le début de la section sur [[#Le TD1 et le TP0 | le TD1 et TP0]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vous pouvez aller discuter des corrections dans les sujets de discussions associes...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD1 et le TP0==&lt;br /&gt;
&lt;br /&gt;
Pour vous montrer un exemple de ce que j&#039;attends, voila la correction de la fonction factorielle. (C&#039;était facile...) J&#039;ai volontairement mis beaucoup de commentaires...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;La fonction factorielle (TD1, exercice 2, question 2)&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but est de calculer la fonction &amp;lt;math&amp;gt;!n = 1\times2\times \cdots \times n&amp;lt;/math&amp;gt; par récurrence. La version typée est verbeuse de la fonction correspondante en Caml donne :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* fonction factorielle : c&#039;est la factorielle habituelle des mathématiciens... *)&lt;br /&gt;
let rec fact (n:int) : int =&lt;br /&gt;
  if (n&amp;gt;1)&lt;br /&gt;
  then  n * (fact (n-1))&lt;br /&gt;
  else 1      (* rq : pour que le programme ne boucle pas sur les valeurs négatives, on renvoie 1 dés que n&amp;lt;1 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme la fonction est récursive, il ne faut pas oublier le &amp;lt;tt&amp;gt;rec&amp;lt;/tt&amp;gt; au début de la définition.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On aurait pu faire une autre version, qui fonctionne différemment sur les nombres négatifs :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fact&#039; = function&lt;br /&gt;
   n when (n&amp;gt;0) -&amp;gt; n * fact&#039; (n-1)&lt;br /&gt;
 | n when (n&amp;lt;0) -&amp;gt; n * fact&#039; (n+1)&lt;br /&gt;
 | _ -&amp;gt; 1  (* si n n&#039;est ni plus petit que 0 ni plus grand que 0, n est égal à 0, et on renvoie donc 1 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;ai volontairement mis une version qui contient plusieurs choses que nous n&#039;avons pas encore vues en cours :&lt;br /&gt;
* utilisation de &amp;quot;&amp;lt;tt&amp;gt;function&amp;lt;/tt&amp;gt;&amp;quot; plutôt que &amp;lt;tt&amp;gt;fun&amp;lt;/tt&amp;gt;,&lt;br /&gt;
* le symbole &amp;quot;&amp;lt;tt&amp;gt;|&amp;lt;/tt&amp;gt;&amp;quot;,&lt;br /&gt;
* le mot clé &amp;quot;&amp;lt;tt&amp;gt;when&amp;lt;/tt&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Vous devriez pouvoir comprendre ce que fait la fonction. Sinon, voici une version que vous auriez pu écrire :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fact_bis = fun n -&amp;gt;&lt;br /&gt;
  if (n=0)&lt;br /&gt;
  then 1&lt;br /&gt;
  else begin&lt;br /&gt;
    if (n&amp;gt;0)&lt;br /&gt;
    then n*fact_bis (n-1)&lt;br /&gt;
    else n*fact_bis (n+1)   (* dans ce cas, n est forcement négatif *)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Les fonctions sommes &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il s&#039;agit ici d&#039;écrire la fonction qui va additionner les carrés des entiers de 1 jusqu&#039;à un nombre donné.&lt;br /&gt;
&lt;br /&gt;
Cela donne :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_carre b =&lt;br /&gt;
if (b=0) then 0&lt;br /&gt;
else (b*b) + somme_carre (b-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite on nous demande de calculer la somme des cubes des entiers de 1 jusqu&#039;à un nombre donné. On pourrait faire le même programme en remplaçant b*b par b*b*b, mais on va définir une fonction puissance (car elle n&#039;existe pas d&#039;origine sous Caml), qui nous servira aussi pour la suite... :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec puissance x a =&lt;br /&gt;
if (a = 0) then 1&lt;br /&gt;
else x * puissance x (a-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On doit maintenant calculer la somme des &amp;lt;math&amp;gt;i^i&amp;lt;/math&amp;gt;, i variant de 1 à un nombre donné :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_puissance b =&lt;br /&gt;
if (b=0) then 0&lt;br /&gt;
else (puissance b b) + somme_puissance (b-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut définir une unique fonction qui permettrait de faire toutes ces sommes, celle-ci aura pour argument une fonction quelconque :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_fonction n f = (* f étant une fonction *)&lt;br /&gt;
if (n=0) then f 0&lt;br /&gt;
else f n + somme_fonction (n-1) f;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
cette fonction est de type &amp;quot;&amp;lt;tt&amp;gt;int -&amp;gt; fun -&amp;gt; int&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Nombres pairs et impairs (TP0 Partie 2 Question 2) &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut écrire les fonctions récursives pairs et impairs, qui renvoient vrai si le nombre est pair (respectivement impair) et faux si le nombre est impair (respectivement pair);&lt;br /&gt;
Ici nous devons déclarer simultanément les deux fonctions, car chacune fait appel à l&#039;autre lors de son exécution.&lt;br /&gt;
&lt;br /&gt;
Cela donne :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec pair n =&lt;br /&gt;
  if (n=0) then true&lt;br /&gt;
  else impair (n-1)&lt;br /&gt;
and impair n =&lt;br /&gt;
  if (n=0) then false&lt;br /&gt;
  else  pair (n-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Suite de Fibonacci &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La suite de fibonacci est tel que u&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;=0 u&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;=1 et u&amp;lt;sub&amp;gt;n+2&amp;lt;/sub&amp;gt;=u&amp;lt;sub&amp;gt;n+1&amp;lt;/sub&amp;gt;+u&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib n =&lt;br /&gt;
if (n=0) then 0&lt;br /&gt;
else if (n=1) then 1&lt;br /&gt;
else fib (n-1) + fib (n-2);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La plus grande valeur que l&#039;on peut obtenir sans que cela soit trop long est 24157817, ce qui correspond à fib 37.&lt;br /&gt;
Nous trouvons qu&#039;il faut déjà 88 additions pour calculer fib 10.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Rq :&#039;&#039;&#039; fib de 37 prend effectivement beaucoup de temps. Il faut 39088168 additions avant d&#039;en arriver à bout. Il est possible de faire une version de Fibonacci qui va très vite et qui calcule &amp;lt;tt&amp;gt;fib 37&amp;lt;/tt&amp;gt; en seulement 36 additions...&lt;br /&gt;
: Comment ?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Dragon ! &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;i&amp;gt; Le dragon est une créature mythique, présente dans de nombreuses cultures.&lt;br /&gt;
  On peut déterminer deux grands types de dragons : le dragon occidental et le dragon oriental&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction dragon a pour but de dessiner un dragon, pour cela on utilise une fonction récursive qui admet pour argument le nombre n d&#039;itération de la fonction, et les coordonnées de 2 points. A chaque itération, la fonction calcule pour chaque segment, un nouveau point et le relie ensuite aux deux autres.&lt;br /&gt;
&lt;br /&gt;
On obtient en tout 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; segments entremêlés, qui forment un dragon.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s go !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec dragon (n:int) (a:int) (b:int) (c:int) (d:int) : unit =&lt;br /&gt;
if (n = 0) then (moveto a b ; lineto c d)&lt;br /&gt;
               else begin&lt;br /&gt;
                      let x = (a+c+d-b)/2 in&lt;br /&gt;
                      let y = (b+d+a-c)/2 in&lt;br /&gt;
                      dragon (n-1) a b x y ;&lt;br /&gt;
                      dragon (n-1) c d x y&lt;br /&gt;
                    end ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Rq : &#039;&#039;&#039; votre version du dragon est bien, mais pas très précises. (Je chipote un peu...)  Pour les paramètres (&amp;lt;tt&amp;gt;dragon 11 100 100 400 400&amp;lt;/tt&amp;gt;), de nombreux carrés ne sont pas bien tracés.&lt;br /&gt;
:Comment expliquez-vous cela, et comment pouvez-vous le corriger ?&lt;br /&gt;
&lt;br /&gt;
::Pour améliorer la précision je suggère de passer les coordonnées en type Float. --[[Utilisateur:Nicolas|Nicolas]] 31 janvier 2009 à 11:42 (CET)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD2==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exercice 1 : Tuples&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 4 :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
On définit la fonction curry par:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let curry (f: &#039;a * &#039;b -&amp;gt; &#039;c) : &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;c&lt;br /&gt;
     = fun x y -&amp;gt; f(x,y);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ou encore en simplifiant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let curry f x y = f(x,y);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On définit ensuite la fonction uncurry par:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry (f: &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;c) : &#039;a * &#039;b -&amp;gt; &#039;c&lt;br /&gt;
     = fun x -&amp;gt; f (fst x) (snd x);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ou encore de trois autres manières plus simplifiées:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = fun x -&amp;gt; f (fst x) (snd x);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = fun x -&amp;gt; match x with (a,b) -&amp;gt; f a b;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = function (a,b) -&amp;gt; f a b;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Avantage de la première forme (à plusieurs arguments): Elle permet une application partielle: on peut appliquer cette fonction à une seule partie des arguments.&lt;br /&gt;
&lt;br /&gt;
Inconvénients de la seconde forme (à un argument): &lt;br /&gt;
*il faut faire appel à fst, snd;&lt;br /&gt;
*Caml doit séparer les paires: c&#039;est une perte de temps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 5 :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
D&#039;après la fonction récursive Fibonacci définit par &amp;lt;br /&amp;gt;&lt;br /&gt;
f(0)=0 &amp;lt;br /&amp;gt;&lt;br /&gt;
f(1)=1 &amp;lt;br /&amp;gt;&lt;br /&gt;
f(n+2)=f(n+1)+f(n), &amp;lt;br /&amp;gt;&lt;br /&gt;
comment compter le nombre d&#039;appels récursifs en Caml? &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* la fonction renvoie une valeur de type int*int :&lt;br /&gt;
  - la première composante est la valeur de Fibonacci pour n,&lt;br /&gt;
  - la seconde composante est le nonbre d&#039;appels recursifs effectués *)&lt;br /&gt;
 let rec fib n =&lt;br /&gt;
     if (n&amp;lt;2) then (n,0)&lt;br /&gt;
     else let t = fib (n-1) in&lt;br /&gt;
          let s = fib (n-2) in &lt;br /&gt;
     (fst t + fst s , snd t + snd s + 1)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&#039;&#039;exemple : &#039;&#039;fib 10 = (55, 88) pour exécuter la fonction Fibonacci(10), il y a 88 appels récursifs nécessaires...&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exercice 2 : Listes&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 5 :&#039;&#039;&#039;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
suite à l&#039;étude des fonctions &lt;br /&gt;
*longueur&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec longueur l =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; 0&lt;br /&gt;
     | _::l -&amp;gt; 1 + longueur l&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*applique&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec app f p =&lt;br /&gt;
     match p with &lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
     | a :: p -&amp;gt; f(a) :: app f p&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*concatene&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec cat l1 l2 =&lt;br /&gt;
     match l1 with&lt;br /&gt;
     [] -&amp;gt; l2&lt;br /&gt;
     | a :: l -&amp;gt; a :: (cat l l2)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*renverse,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec renverse l =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
     | a :: l -&amp;gt; (renverse l) @ [a]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
on remarque des similitudes. Ces fonctions ont le même schéma de base. On peut résumer le principe commun dans la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec reduit l o f =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; o&lt;br /&gt;
     | a :: l -&amp;gt; let appel_rec = reduit l o f in&lt;br /&gt;
                 f a appel_rec&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&#039;&#039;NB :&#039;&#039; le type de &amp;lt;tt&amp;gt;reduit&amp;lt;/tt&amp;gt; donné par Caml est : &amp;lt;tt&amp;gt;val reduit : &#039;a list -&amp;gt; &#039;b -&amp;gt; (&#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b) -&amp;gt; &#039;b = &amp;lt;fun&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 6 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
Reprogrammons les fonctions précédentes à partir de la fonction reduit ! &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let longueur l =&lt;br /&gt;
     let f _ r = 1 + r in &lt;br /&gt;
     reduit l 0 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let app g l =&lt;br /&gt;
     let f a r = (g a)::r in&lt;br /&gt;
     reduit l [] f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let cat l1 l2 =&lt;br /&gt;
     let f a r = a :: r in  &lt;br /&gt;
     reduit l1 l2 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut également introduire la fonction directement avec un &amp;lt;tt&amp;gt;fun&amp;lt;/tt&amp;gt; de la maniere suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let renverse l = reduit l [] (fun a r -&amp;gt; r @ [a])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 7 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le type de la fonction reduit est: ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b ) -&amp;gt; &#039;a list &amp;lt;br/&amp;gt;&lt;br /&gt;
Celui de la fonction List.fold_right est: ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b ) -&amp;gt; &#039;a list -&amp;gt; &#039;b -&amp;gt; &#039;b  ;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
l&#039;ordre des arguments de fold_right est le même que l&#039;ordre des arguments de reduit. La fonction fold_right compte juste deux arguments supplémentaires.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 8 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici la fonction fold_left:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let rec fold_left f b l=&lt;br /&gt;
      match l with&lt;br /&gt;
        []-&amp;gt;b&lt;br /&gt;
       |a::l -&amp;gt; fold_left f (f b a) l;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Cette fonction est &#039;&#039;récursive terminale&#039;&#039;, de type ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;a ) -&amp;gt; &#039;a -&amp;gt; &#039;b list -&amp;gt; &#039;a .&lt;br /&gt;
&lt;br /&gt;
==Le TP1 - début==&lt;br /&gt;
&lt;br /&gt;
Le sujet [http://www.lama.univ-savoie.fr/~hyvernat/Enseignement/0809/info401/tp1.pdf programmes récursifs, listes], au format pdf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 1 : Quelques compléments sur les programmes récursifs&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans cette partie, on travaille sur la fonction Fibonacci&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On commence par l&#039;utiliser sous la forme :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib n =&lt;br /&gt;
if n&amp;lt;2&lt;br /&gt;
   then n&lt;br /&gt;
   else fib (n-1) + fib (n-2)&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comprendre ce qu&#039;il se passe, on trace la fonction à l&#039;aide de &amp;quot;#trace&amp;quot; pour fib 5&lt;br /&gt;
&lt;br /&gt;
fib &amp;lt;-- n veut dire que l&#039;on donne la valeur n à la fonction fib&lt;br /&gt;
&lt;br /&gt;
alors que fib --&amp;gt; n veut dire que fib renvoie n&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib 5 ;;&lt;br /&gt;
fib &amp;lt;-- 5&lt;br /&gt;
fib &amp;lt;-- 3&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib &amp;lt;-- 2&lt;br /&gt;
fib &amp;lt;-- 0&lt;br /&gt;
fib --&amp;gt; 0&lt;br /&gt;
...&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib &amp;lt;-- 2&lt;br /&gt;
fib &amp;lt;-- 0&lt;br /&gt;
fib --&amp;gt; 0&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib --&amp;gt; 2&lt;br /&gt;
fib --&amp;gt; 3&lt;br /&gt;
fib --&amp;gt; 5&lt;br /&gt;
- : int = 5&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut remarquer que la fonction calcule plusieurs fois le même fib n.&lt;br /&gt;
Une optimisation consisterait à garder certaines valeurs en mémoire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On écrit fib2 de type &amp;quot;int -&amp;gt; int*int&amp;quot; qui renvoie le valeur de fib n (fst fib2 n) et fib n-1 (snd (fib2 n)) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib2 n = &lt;br /&gt;
if n&amp;lt;2 &lt;br /&gt;
   then (n,n-1)&lt;br /&gt;
   else let t = fib2 (n-1) in&lt;br /&gt;
      (fst(t)+snd(t),fst(t));;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 3&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comparer les fonctions fib et fib2, on les trace pour n=7 :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib 7 ;;&lt;br /&gt;
fib &amp;lt;-- 7&lt;br /&gt;
fib &amp;lt;-- 5&lt;br /&gt;
fib &amp;lt;-- 3&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
...&lt;br /&gt;
fib --&amp;gt; 3&lt;br /&gt;
fib --&amp;gt; 5&lt;br /&gt;
fib --&amp;gt; 8&lt;br /&gt;
fib --&amp;gt; 13&lt;br /&gt;
- : int = 13&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib2 7 ;;&lt;br /&gt;
fib2 &amp;lt;-- 7&lt;br /&gt;
fib2 &amp;lt;-- 6&lt;br /&gt;
fib2 &amp;lt;-- 5&lt;br /&gt;
fib2 &amp;lt;-- 4&lt;br /&gt;
fib2 &amp;lt;-- 3&lt;br /&gt;
fib2 &amp;lt;-- 2&lt;br /&gt;
fib2 &amp;lt;-- 1&lt;br /&gt;
fib2 --&amp;gt; (1, 0)&lt;br /&gt;
fib2 --&amp;gt; (1, 1)&lt;br /&gt;
fib2 --&amp;gt; (2, 1)&lt;br /&gt;
fib2 --&amp;gt; (3, 2)&lt;br /&gt;
fib2 --&amp;gt; (5, 3)&lt;br /&gt;
fib2 --&amp;gt; (8, 5)&lt;br /&gt;
fib2 --&amp;gt; (13, 8)&lt;br /&gt;
- : int * int = (13, 8)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On remarque que fib2 fait 14 calculs alors que fib en 81 pour n=7.&lt;br /&gt;
Afin de retourner uniquement la valeur de fib n on définit une nouvelle fonction, beaucoup plus rapide que fib, &lt;br /&gt;
en prenant le premier élément de la paire constituant fib2 n :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let fib n = fst ( fib2 n ) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 4 ( Bonus )&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On veut créer fib3 de type int-&amp;gt;int-&amp;gt;int-&amp;gt;int tel que :&lt;br /&gt;
&lt;br /&gt;
- son premier argument est l&#039;entier n pour fibonacci de n&lt;br /&gt;
&lt;br /&gt;
- les 2 autres arguments sont des accumulateurs qui permettent de conserver des valeurs successives ( pour i-1 et i )&lt;br /&gt;
&lt;br /&gt;
 --- à venir ---&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 2 : Manipulation des listes&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici quelque fonctions définies en utilisant &amp;lt;tt&amp;gt;List.fold_right&amp;lt;/tt&amp;gt; :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let longueur l = let f a r = 1 + r in List.fold_right f l 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let app f l = let f&#039; a r = ( f a )::r in List.fold_right f&#039; l []&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let concat l1 l2 = let f a r = a::r in List.fold_right l1 l2 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici la fonction reverse telle qu&#039;on l&#039;a écrite dans le TD&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec reverse l = &lt;br /&gt;
  match l with&lt;br /&gt;
  []-&amp;gt;[]&lt;br /&gt;
  |a::l -&amp;gt; (reverse l)@[a] ;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour la comparer avec la fonction &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; de Caml, on va regarder le temps d&#039;exécution sur une très grande liste.&lt;br /&gt;
&lt;br /&gt;
Pour cela, on créé une fonction qui fabrique une liste de n valeurs :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec longueliste  n = &lt;br /&gt;
  if n=0 &lt;br /&gt;
  then []&lt;br /&gt;
  else n::longueliste (n-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut tester les fonctions avec une liste de 10000 éléments.&lt;br /&gt;
&lt;br /&gt;
La fonction &amp;lt;tt&amp;gt;reverse&amp;lt;/tt&amp;gt; met environ 15s alors que &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; s&#039;exécute immédiatement.&lt;br /&gt;
&lt;br /&gt;
Cela montre donc que &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; est bien plus efficace que &amp;lt;tt&amp;gt;reverse&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::En fait, reverse fait ( n + n-1 + n-2 + ... + 1 ) opérations à chaque fois (il met le premier élément au bout de la liste et ainsi de suite) , soit au total &amp;lt;math&amp;gt;n*(n+1)/2 \sim n^2&amp;lt;/math&amp;gt; opérations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; utilise la fonction suivante :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec rev_append l1 l2 =&lt;br /&gt;
  match l1 with&lt;br /&gt;
    [] -&amp;gt; l2&lt;br /&gt;
  | a::l -&amp;gt; rev_append l (a::l2);;&lt;br /&gt;
&lt;br /&gt;
let rec rev l = rev_append l [];;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Elle fait donc environ &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; opérations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 3 : Deux algorithmes de tri pour les listes&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On programme une fonction d&#039;insertion qui permet d&#039;insérer un élément à sa place&lt;br /&gt;
dans une liste triée.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insertion n l =&lt;br /&gt;
  match l with&lt;br /&gt;
    [] -&amp;gt; [n]&lt;br /&gt;
  | a::l&#039; -&amp;gt; if n&amp;lt;=a&lt;br /&gt;
             then n::l&lt;br /&gt;
             else a::(insertion n l&#039;) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On programme ensuite le tri par insertion.&lt;br /&gt;
&lt;br /&gt;
Le tri par insertion fonctionne de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
- la liste vide est triée,&lt;br /&gt;
&lt;br /&gt;
- pour trier la liste &amp;quot;&amp;lt;tt&amp;gt;a::l&amp;lt;/tt&amp;gt;&amp;quot;, on commence par trier (récursivement) la liste &amp;lt;tt&amp;gt;l&amp;lt;/tt&amp;gt;, puis on insère&lt;br /&gt;
l&#039;élément &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; dans le résultat.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec tri_insertion l =&lt;br /&gt;
 match l with&lt;br /&gt;
    [] -&amp;gt; []&lt;br /&gt;
  | a::l&#039; -&amp;gt; insertion a (tri_insertion l&#039;) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ou plus simplement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let tri l = List.fold.right insertion l [] ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 3&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Maintenant, on programme une fonction fusionne qui permet de fusionner deux listes triées en une seule liste triée.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionne l1 l2 =&lt;br /&gt;
  match l1 with &lt;br /&gt;
     [] -&amp;gt; l2&lt;br /&gt;
   | a::l&#039; -&amp;gt; begin&lt;br /&gt;
                match l2 with&lt;br /&gt;
                   [] -&amp;gt; l1&lt;br /&gt;
                 | b::l&#039;&#039; -&amp;gt; if a&amp;lt;=b then ( a::fusionne l&#039; l2 ) &lt;br /&gt;
                                     else ( b::fusionne l1 l&#039;&#039;) &lt;br /&gt;
&lt;br /&gt;
              end;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour éviter d&#039;imbriquer des &amp;quot;match&amp;quot;, on peut aussi filtrer directement la paire &amp;lt;tt&amp;gt;(l1,l2)&amp;lt;/tt&amp;gt; et regrouper les cas d&#039;un des listes vides ensemble : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionnebis l1 l2 =&lt;br /&gt;
  match l1,l2 with&lt;br /&gt;
      [],l | l,[]  -&amp;gt;  l&lt;br /&gt;
    | (a::l&#039;, b::l2&#039;)  -&amp;gt; &lt;br /&gt;
        if a &amp;lt;= b&lt;br /&gt;
        then a::(fusionnebis l&#039; l2)&lt;br /&gt;
        else b::(fusionnebis l1 l2&#039;)  ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 4&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis une fonction sépare qui permet de séparer une liste quelconque en&lt;br /&gt;
deux listes de taille équivalente&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec separe l =&lt;br /&gt;
  match l with&lt;br /&gt;
     [] -&amp;gt; ([],[])&lt;br /&gt;
   | [a] -&amp;gt; ([a],[])&lt;br /&gt;
   | a::b::l&#039; -&amp;gt; let t=separe l&#039; in (a::(fst t),b::(snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 5&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On doit maintenant programmer un deuxième type de tri : le tri par fusion.&lt;br /&gt;
&lt;br /&gt;
Le tri fusion fonctionne de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
- la liste vide est triée,&lt;br /&gt;
&lt;br /&gt;
- pour trier une liste non-vide, on sépare la liste en deux parties de longueur égale (à un&lt;br /&gt;
élément prêt), on trie (récursivement) ces deux listes, puis on fusionne les deux résultats.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec tri_fusion l =  &lt;br /&gt;
  match l with&lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
   | [a] -&amp;gt; [a]&lt;br /&gt;
   | _ -&amp;gt; let t=separe l in&lt;br /&gt;
          fusionne (tri_fusion (fst t)) (tri_fusion (snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 6&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comparer l&#039;efficacité des deux fonctions de tri, on utilise la même méthode que précédemment : &lt;br /&gt;
&lt;br /&gt;
On créé a l&#039;aide d&#039;un fonction une liste aléatoire de 10000 éléments, les éléments étant non triés.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let liste_aleatoire n =&lt;br /&gt;
  let rec aux n max = &lt;br /&gt;
    if n=0&lt;br /&gt;
    then []&lt;br /&gt;
    else (Random.int max)::aux (n-1) max&lt;br /&gt;
  in&lt;br /&gt;
  aux n n ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite on trie cette liste avec les deux fonctions.&lt;br /&gt;
&lt;br /&gt;
Le tri_fusion renvoie instantanément une liste de 10000 éléments aléatoires triés. &lt;br /&gt;
&lt;br /&gt;
Le tri insertion, quant à lui, prend plus d&#039;une dizaine de secondes.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;Remarque :&#039;&#039; cela vient du fait que le tri fusion divise la taille de la liste par deux à chaque étape, alors que le tri par insertion soustrait un élément à chaque étape.&lt;br /&gt;
: On peut montrer que le temps de calcul pour le tri fusion est proportionnel à &amp;lt;math&amp;gt;n \log(n)&amp;lt;/math&amp;gt;, ce qui est très petit par rapport à &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt; (temps d&#039;execution moyen du tri par insertion) quand &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; est grand.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 7&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On souhaite trier une liste selon la hauteur des points c&#039;est-à-dire selon le deuxième élément de la paire de flottants.&lt;br /&gt;
Pour cela, il faudrait faire un tri fusion sur le 2eme élément de la paire représentant les points&lt;br /&gt;
tout en sauvegardant le 1er élément...&lt;br /&gt;
&lt;br /&gt;
On peut créer une fonction de tri par fusion générale, qui prend comme paramètre une autre fonction (qui sert à vérifier la comparaison de 2 éléments et rend true ou false) afin de choisir le tri que l&#039;on veut ( décroissant, croissant ... ) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionne comp l1 l2 =&lt;br /&gt;
 match (l1,l2) with&lt;br /&gt;
    ([],_) -&amp;gt; l2&lt;br /&gt;
  | (_,[]) -&amp;gt; l1&lt;br /&gt;
  | (a::l&#039;, b::l2&#039;) -&amp;gt; &lt;br /&gt;
     if (comp a b)&lt;br /&gt;
     then a::(fusionne l&#039; l2)&lt;br /&gt;
     else b::(fusionne l1 l2&#039;);;&lt;br /&gt;
&lt;br /&gt;
let rec tri_fusion comp l =  &lt;br /&gt;
 match l with&lt;br /&gt;
    [] -&amp;gt; []&lt;br /&gt;
  | [a] -&amp;gt; [a]&lt;br /&gt;
  | _ -&amp;gt; let t=separe l in&lt;br /&gt;
         fusionne comp (tri_fusion comp (fst t)) (tri_fusion comp (snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il suffit alors a l&#039;utilisateur de définir la fonction de comparaison pour ensuite faire appel à &amp;lt;tt&amp;gt;tri_fusion&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Par exemple, pour trier dans un ordre décroissant :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let dec a n  = if a&amp;gt;=n then true&lt;br /&gt;
else false ;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
ou même plus simplement&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let dec = (&amp;gt;=) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour trier une liste de paires, il faut créer une fonction qui compare les seconds membres ;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let paire a n  = (snd a) &amp;lt;= (snd n)  ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ici, les paires seront triées selon le second membre dans l&#039;ordre croissant.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 8 ( Bonus )&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un algorithme de tri est dit stable quand il ne modifie pas l&#039;ordre relatifs des éléments &amp;quot;égaux&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Par exemple, on tri par ordre croissant du premier membre une liste de paires de float : [ ( 5 , 3 ) ; ( -2 , 8 ) ; ( -2 , 2 ) ; ( 5 , 8 ) ; ( 5 , -8 ) ]  &lt;br /&gt;
&lt;br /&gt;
non stable : &amp;lt;tt&amp;gt;[(-2, 2); (-2, 8); (5, -8); (5, 8); (5, 3)]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
stable : &amp;lt;tt&amp;gt;[(-2, 8); (-2, 2); (5, 3); (5, 8); (5, -8)]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour qu&#039;un tri soit stable, la comparaison de deux éléments doit comprendre aussi le &amp;quot;=&amp;quot;, comme c&#039;est le cas pour les fonctions paire et dec.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD3==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Exercice 1 : les arbres binaires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt; Question 1 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type &#039;a arbre = Vide | Noeud of &#039;a*&#039;a arbre*&#039;a arbre ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 2 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
let rec taille a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; 1 + (taille g) + (taille d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction taille compte le nombre de noeuds que contient un arbre.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 3 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec applique f a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; Vide&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; Noeud(f e,applique f g,applique f d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction applique est équivalente à la fonction List.map&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 4 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec poids (f : &#039;a -&amp;gt; int) a = &lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; (f e) + (poids f g) + (poids f d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 5 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec reduit a o f =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; let x = reduit g o f in&lt;br /&gt;
       			let y = reduit d o f in&lt;br /&gt;
                        f e x y ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction reduit est equivalente à la fonction List.fold_right pour le type des arbres.&lt;br /&gt;
&lt;br /&gt;
Réécriture de taille et poids :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec taille a = reduit a 0 (fun e x y -&amp;gt; 1 + x + y) ;;&lt;br /&gt;
let rec poids f a = reduit a 0 (fun e x y -&amp;gt; (f e) + (f x) + (f y)) ;; (*?????*)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 6 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec collecte a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; []&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; e::(collecte g)@(collecte d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction collecte récupère tous les éléments de l&#039;arbre et les renvoie sous forme d&#039;une liste.&lt;br /&gt;
&lt;br /&gt;
Avec la fonction reduit :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec collecte a = reduit a [] (fun e x y -&amp;gt; e::x@y) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 7 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec feuilles a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; []&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; if (g=Vide &amp;amp;&amp;amp; d=Vide) then [e]&lt;br /&gt;
       			else (feuilles g)@(feuilles d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Avec reduit :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec feuilles a = reduit a [] (fun e x y -&amp;gt; if (x=[] &amp;amp;&amp;amp; y=[]) then [e]&lt;br /&gt;
					       else x@y) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Exercice 2 : la tortue &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt; Question 1 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type action = Forward of int | Left of int | SetPos of int*int | SetHeading of int | PenUp | Pendown ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 2 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
let rec ecrit (l:action list) (pen:bool) : bool =&lt;br /&gt;
   match l with&lt;br /&gt;
    	[] -&amp;gt; false&lt;br /&gt;
       |(Forward d)::l -&amp;gt; if (d=0 || pen=false) then ecrit l pen&lt;br /&gt;
                          else true &lt;br /&gt;
       |PenUp::l -&amp;gt; ecrit l false&lt;br /&gt;
       |PenDown::l -&amp;gt; ecrit l true&lt;br /&gt;
       | _ -&amp;gt; ecrit l pen ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction ecrit renvoie true si la tortue écrit qqch ou false sinon.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 3 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec pos (x:int) (y:int) (a:int) (l:action list) : ((int*int)int) =&lt;br /&gt;
   match l with&lt;br /&gt;
    	[] -&amp;gt; ((x,y),a)&lt;br /&gt;
       |PenUp::l |Pendown::l -&amp;gt; pos x y a l&lt;br /&gt;
       |(Left b)::l -&amp;gt; pos x y (a+b) l&lt;br /&gt;
       |(SetPos(x&#039;,y&#039;))::l -&amp;gt; pos x&#039; y&#039; a l&lt;br /&gt;
       |(SetHeading b)::l -&amp;gt; pos x y b l &lt;br /&gt;
       |(Forward d)::l -&amp;gt; pos (x+(sin a)*d) (y+(cos a)*d) a l ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 5 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type action = Forward of int | SetPos of int*int | SetHeading of int | Left of int | PenUp | Pendown | Repeat of int*action list ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD4==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 1 : Petits exercices combinatoires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On commence par créer une fonction intermédiaire.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supp&#039; x l =&lt;br /&gt;
   match l with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |b::f&#039;-&amp;gt; if (x=b) then supp&#039; x l&#039;&lt;br /&gt;
                        else b::supp&#039; x f&#039;;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supp l =&lt;br /&gt;
   match l with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |a::l&#039;-&amp;gt; a::supp supp&#039; a l&#039;;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 2 : Dictionnaires &amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Un dictionnaire est une liste de paires&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Question 2 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insere c v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[(c,v)]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (c=c&#039;) then (c&#039;,v&#039;)::(insere c v d)&lt;br /&gt;
                               else (c,v)::d ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supprime c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (c=c&#039;) then d&lt;br /&gt;
                               else (c&#039;,v&#039;)::(supprime c d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec existe_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; false&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; (c=c&#039;) || existe_cle c d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec existe_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; false&lt;br /&gt;
      |(_,v&#039;)::d -&amp;gt; if (v=v&#039;) then true&lt;br /&gt;
                              else existe_val v d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec recherche_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; None&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; if (c=c&#039;) then Some c&#039;&lt;br /&gt;
                              else recherche_cle c d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* liste des valeurs de c par on peut avoir plusieurs cases, et donc plusieurs clés, avec une même valeur *)&lt;br /&gt;
let rec recherche_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (v=v&#039;) then c&#039;::(recherche_val v d)&lt;br /&gt;
                              else recherche_val v d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Liste des clés *)&lt;br /&gt;
let rec liste_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; []&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; c&#039;::(liste_cle c d);;&lt;br /&gt;
&lt;br /&gt;
(* Liste des valeurs *)&lt;br /&gt;
let rec liste_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(_,v&#039;)::d -&amp;gt; v&#039;::(liste_val v d);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut également utiliser des fonctions existantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Liste des clés *)&lt;br /&gt;
let liste_cle d = List.map fst;;&lt;br /&gt;
&lt;br /&gt;
(* Liste des valeurs, attention aux doublons! *)&lt;br /&gt;
let liste_val d = suppr_doublons(List.map snd);;&lt;br /&gt;
  &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 4 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec zip l1 l2&lt;br /&gt;
   match l1 l2 with&lt;br /&gt;
      [].[]-&amp;gt;[]&lt;br /&gt;
      |c::lc, v::lv -&amp;gt; (c,v)::(zip lc lv)&lt;br /&gt;
      |_,_ -&amp;gt; [];;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 5 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On aurait pu utiliser une liste triée : si par exemple on cherche 12 et qu&#039;on en est à 14 dans la liste, on sait que 12 n&#039;y est pas. PB : ceci n&#039;empêche pas d&#039;aller à la fin de la liste si la valeur ou la clé recherchée est grande ... &amp;lt;br/&amp;gt;&lt;br /&gt;
Une recherche dichotomique est inefficace sur les listes ... &amp;lt;br/&amp;gt;&lt;br /&gt;
   =&amp;gt; dans la bibliothèque hash table de Caml, il existe un List.zip&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 3 : Arbres binaires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Question 1 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
La profondeur d&#039;un arbre binaire correspond au nombre d&#039;étage : on regarde à partir de la première racine et des sous arbres, on calcule la profondeur à gauche et la profondeur à droite, on prend la plus grande et on y ajoute 1. &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec profondeur a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; 0&lt;br /&gt;
      |Noeud(_,g,d) -&amp;gt; 1 + max(profondeurg) (profondeurd);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 2 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec equilibre a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; true&lt;br /&gt;
      |Noeud(_,g,d) -&amp;gt; if (profondeur g)=(profondeur d) || (profondeur g)=(profondeur d +1) || (profondeur g +1)=(profondeur d)&lt;br /&gt;
                          then (equilibre d)&amp;amp;&amp;amp;(equilibre g)&lt;br /&gt;
                          else false;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec present e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; false&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; e&#039;=e || present e g || present e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 4 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec present e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; false&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; if (e&#039;=e) then true&lt;br /&gt;
                                  else  if (e&amp;lt;e&#039;) then present e g&lt;br /&gt;
                                                  else present e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 5 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insere e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; e&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; if (e&amp;lt;e&#039;) then insere e g&lt;br /&gt;
                                  else insere e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Le TP2==&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt;Partie 1&amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
QUESTION 1 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction suivante permet de calculer les ensemble de nombre. Elle est réalisé à l&#039;aide d&#039;une concaténation de la liste précédente avec la liste modifier ainsi que List.map.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
open List&lt;br /&gt;
&lt;br /&gt;
let rec sous_ensemble n=&lt;br /&gt;
    if n=0&lt;br /&gt;
    then &lt;br /&gt;
      [[]]&lt;br /&gt;
    else&lt;br /&gt;
      let liste = sous_ensemble (n-1) in (List.map (fun l-&amp;gt;n::l) liste) @ liste&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 2 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction supprime doublon est réalisé tout d&#039;abord en triant la liste puis en regardant si deux éléments concécutif sont les mêmes, si oui on en supprime un.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec lstTrier liste=&lt;br /&gt;
  match liste with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
    | [a]-&amp;gt;liste&lt;br /&gt;
    | a::b::liste-&amp;gt;if a=b then lstTrier (a::liste)&lt;br /&gt;
                          else a::lstTrier (b::liste)&lt;br /&gt;
&lt;br /&gt;
let supprime_doublon lst=&lt;br /&gt;
 lstTrier (List.sort (-) lst)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt;Partie 2&amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
QUESTION 1 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction taille calcul la taille d&#039;un arbre, on incrémente un compteur dès que l&#039;on rencontre un noeud. &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec taille (arbre:&#039;a arbre)=&lt;br /&gt;
  match arbre  with&lt;br /&gt;
    Vide     -&amp;gt; 0&lt;br /&gt;
  | Noeud(_,a,b) -&amp;gt; 1 + taille a+taille b&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
la fonction applique permet d&#039;appliquer une fonction a tous les éléments d&#039;un arbre.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec applique (fc:&#039;a-&amp;gt;&#039;b) arbre=&lt;br /&gt;
  match arbre with&lt;br /&gt;
    Vide-&amp;gt;Vide&lt;br /&gt;
  | Noeud(a,b,c)-&amp;gt;Noeud (fc a,applique fc b,applique fc c )&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
la fonction fold renvoie le contenu des feuilles composant l&#039;arbre.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec fold (f:&#039;a-&amp;gt;&#039;b-&amp;gt;&#039;b-&amp;gt;&#039;b) arbre n=&lt;br /&gt;
  match arbre with&lt;br /&gt;
    Vide-&amp;gt;n&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;f a(fold f b n) (fold f c n)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 2 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction feuille crée une liste à partir des éléments retourné par la fonction fold.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec feuilles (f:&#039;a arbre-&amp;gt;&#039;a list) arbre=&lt;br /&gt;
  fold (fun a b c-&amp;gt; if(b=[])&amp;amp;&amp;amp;(c=[]) &lt;br /&gt;
     then [a] &lt;br /&gt;
     else (b@c)) arbre[]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 3 :&amp;lt;br/&amp;gt;&lt;br /&gt;
cette fonction permet de créer un arbre à partir d&#039;une liste, elle regarde la taille des branches afin de pouvoir inserer les éléments de façon à avoir le moins de noeuds possible.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec insert arbre aInsert=&lt;br /&gt;
  match arbre with&lt;br /&gt;
      Vide-&amp;gt;Noeud (aInsert,Vide,Vide)&lt;br /&gt;
    | Noeud (a,b,c)-&amp;gt;if (taille b &amp;lt; taille c) then Noeud(a,(insert b aInsert),c) else Noeud(a,b,(insert c aInsert))&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
let rec construit_arbre_int liste arbre=&lt;br /&gt;
  match liste with &lt;br /&gt;
      [a]-&amp;gt;insert arbre a&lt;br /&gt;
    | a::liste-&amp;gt;construit_arbre_int liste (insert arbre a)&lt;br /&gt;
&lt;br /&gt;
let construit_arbre liste=&lt;br /&gt;
  construit_arbre_int liste Vide&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 4 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction se divise en deux partie : l&#039;une permet d&#039;obtenir la taille minimal d&#039;une branche et l&#039;autre la taille maximal, la fonction affiche ensuite les résultats.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
let rec calcMax arbre compt=&lt;br /&gt;
match arbre with&lt;br /&gt;
    Vide-&amp;gt;compt&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;if (taille b &amp;gt; taille c) then calcMax b compt+1 else calcMax c compt+1&lt;br /&gt;
&lt;br /&gt;
let rec calcMin arbre compt=&lt;br /&gt;
match arbre with&lt;br /&gt;
    Vide-&amp;gt;compt&lt;br /&gt;
  | Noeud (a,b,c)-&amp;gt;if (taille b &amp;lt; taille c) then calcMax b compt+1 else calcMax c compt+1&lt;br /&gt;
&lt;br /&gt;
let profondeurs arbre=&lt;br /&gt;
  (calcMax arbre 0 , calcMin arbre 0)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
QUESTION 5 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction tailleR est la fonction tille pour les arbres binaires.&amp;lt;br/&amp;gt;&lt;br /&gt;
nous pouvons remarquer que la fonction applique pourrait rendre un arbre binaire faux.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
type &#039;a abr = Vide | Noeud of &#039;a abr * &#039;a* &#039;a abr&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
let rec tailleR abr=&lt;br /&gt;
  match abr with&lt;br /&gt;
    Vide     -&amp;gt; 0&lt;br /&gt;
  | Noeud(a,_,b) -&amp;gt; 1 + tailleR a+tailleR b&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
==Contrôle continu 1==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TP3==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD5==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TP4==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==TD6==&lt;/div&gt;</summary>
		<author><name>Laurent corantin</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=INFO401_corr_TD_TP&amp;diff=4147</id>
		<title>INFO401 corr TD TP</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=INFO401_corr_TD_TP&amp;diff=4147"/>
		<updated>2009-04-30T12:34:20Z</updated>

		<summary type="html">&lt;p&gt;Laurent corantin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Préliminaires==&lt;br /&gt;
&lt;br /&gt;
Pour afficher correctement dans le wiki, allez voir un peu comment on fait. Vous pouvez regarder par exemple sur le [[INFO401 | wiki du cours]] ou directement sur des articles de [http://fr.wikipedia.org/wiki/Accueil Wikipedia]. La documentation de mediawiki se trouve [http://meta.wikimedia.org/wiki/Aide:Éditeur ici].&lt;br /&gt;
&lt;br /&gt;
Un truc important : pour rentrer du code Caml, il faut mettre les balises &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;...&amp;lt;/source&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; autour de votre code. Allez par exemple voir le début de la section sur [[#Le TD1 et le TP0 | le TD1 et TP0]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vous pouvez aller discuter des corrections dans les sujets de discussions associes...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD1 et le TP0==&lt;br /&gt;
&lt;br /&gt;
Pour vous montrer un exemple de ce que j&#039;attends, voila la correction de la fonction factorielle. (C&#039;était facile...) J&#039;ai volontairement mis beaucoup de commentaires...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;La fonction factorielle (TD1, exercice 2, question 2)&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but est de calculer la fonction &amp;lt;math&amp;gt;!n = 1\times2\times \cdots \times n&amp;lt;/math&amp;gt; par récurrence. La version typée est verbeuse de la fonction correspondante en Caml donne :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* fonction factorielle : c&#039;est la factorielle habituelle des mathématiciens... *)&lt;br /&gt;
let rec fact (n:int) : int =&lt;br /&gt;
  if (n&amp;gt;1)&lt;br /&gt;
  then  n * (fact (n-1))&lt;br /&gt;
  else 1      (* rq : pour que le programme ne boucle pas sur les valeurs négatives, on renvoie 1 dés que n&amp;lt;1 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme la fonction est récursive, il ne faut pas oublier le &amp;lt;tt&amp;gt;rec&amp;lt;/tt&amp;gt; au début de la définition.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On aurait pu faire une autre version, qui fonctionne différemment sur les nombres négatifs :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fact&#039; = function&lt;br /&gt;
   n when (n&amp;gt;0) -&amp;gt; n * fact&#039; (n-1)&lt;br /&gt;
 | n when (n&amp;lt;0) -&amp;gt; n * fact&#039; (n+1)&lt;br /&gt;
 | _ -&amp;gt; 1  (* si n n&#039;est ni plus petit que 0 ni plus grand que 0, n est égal à 0, et on renvoie donc 1 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;ai volontairement mis une version qui contient plusieurs choses que nous n&#039;avons pas encore vues en cours :&lt;br /&gt;
* utilisation de &amp;quot;&amp;lt;tt&amp;gt;function&amp;lt;/tt&amp;gt;&amp;quot; plutôt que &amp;lt;tt&amp;gt;fun&amp;lt;/tt&amp;gt;,&lt;br /&gt;
* le symbole &amp;quot;&amp;lt;tt&amp;gt;|&amp;lt;/tt&amp;gt;&amp;quot;,&lt;br /&gt;
* le mot clé &amp;quot;&amp;lt;tt&amp;gt;when&amp;lt;/tt&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Vous devriez pouvoir comprendre ce que fait la fonction. Sinon, voici une version que vous auriez pu écrire :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fact_bis = fun n -&amp;gt;&lt;br /&gt;
  if (n=0)&lt;br /&gt;
  then 1&lt;br /&gt;
  else begin&lt;br /&gt;
    if (n&amp;gt;0)&lt;br /&gt;
    then n*fact_bis (n-1)&lt;br /&gt;
    else n*fact_bis (n+1)   (* dans ce cas, n est forcement négatif *)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Les fonctions sommes &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il s&#039;agit ici d&#039;écrire la fonction qui va additionner les carrés des entiers de 1 jusqu&#039;à un nombre donné.&lt;br /&gt;
&lt;br /&gt;
Cela donne :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_carre b =&lt;br /&gt;
if (b=0) then 0&lt;br /&gt;
else (b*b) + somme_carre (b-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite on nous demande de calculer la somme des cubes des entiers de 1 jusqu&#039;à un nombre donné. On pourrait faire le même programme en remplaçant b*b par b*b*b, mais on va définir une fonction puissance (car elle n&#039;existe pas d&#039;origine sous Caml), qui nous servira aussi pour la suite... :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec puissance x a =&lt;br /&gt;
if (a = 0) then 1&lt;br /&gt;
else x * puissance x (a-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On doit maintenant calculer la somme des &amp;lt;math&amp;gt;i^i&amp;lt;/math&amp;gt;, i variant de 1 à un nombre donné :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_puissance b =&lt;br /&gt;
if (b=0) then 0&lt;br /&gt;
else (puissance b b) + somme_puissance (b-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut définir une unique fonction qui permettrait de faire toutes ces sommes, celle-ci aura pour argument une fonction quelconque :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_fonction n f = (* f étant une fonction *)&lt;br /&gt;
if (n=0) then f 0&lt;br /&gt;
else f n + somme_fonction (n-1) f;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
cette fonction est de type &amp;quot;&amp;lt;tt&amp;gt;int -&amp;gt; fun -&amp;gt; int&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Nombres pairs et impairs (TP0 Partie 2 Question 2) &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut écrire les fonctions récursives pairs et impairs, qui renvoient vrai si le nombre est pair (respectivement impair) et faux si le nombre est impair (respectivement pair);&lt;br /&gt;
Ici nous devons déclarer simultanément les deux fonctions, car chacune fait appel à l&#039;autre lors de son exécution.&lt;br /&gt;
&lt;br /&gt;
Cela donne :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec pair n =&lt;br /&gt;
  if (n=0) then true&lt;br /&gt;
  else impair (n-1)&lt;br /&gt;
and impair n =&lt;br /&gt;
  if (n=0) then false&lt;br /&gt;
  else  pair (n-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Suite de Fibonacci &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La suite de fibonacci est tel que u&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;=0 u&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;=1 et u&amp;lt;sub&amp;gt;n+2&amp;lt;/sub&amp;gt;=u&amp;lt;sub&amp;gt;n+1&amp;lt;/sub&amp;gt;+u&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib n =&lt;br /&gt;
if (n=0) then 0&lt;br /&gt;
else if (n=1) then 1&lt;br /&gt;
else fib (n-1) + fib (n-2);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La plus grande valeur que l&#039;on peut obtenir sans que cela soit trop long est 24157817, ce qui correspond à fib 37.&lt;br /&gt;
Nous trouvons qu&#039;il faut déjà 88 additions pour calculer fib 10.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Rq :&#039;&#039;&#039; fib de 37 prend effectivement beaucoup de temps. Il faut 39088168 additions avant d&#039;en arriver à bout. Il est possible de faire une version de Fibonacci qui va très vite et qui calcule &amp;lt;tt&amp;gt;fib 37&amp;lt;/tt&amp;gt; en seulement 36 additions...&lt;br /&gt;
: Comment ?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Dragon ! &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;i&amp;gt; Le dragon est une créature mythique, présente dans de nombreuses cultures.&lt;br /&gt;
  On peut déterminer deux grands types de dragons : le dragon occidental et le dragon oriental&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction dragon a pour but de dessiner un dragon, pour cela on utilise une fonction récursive qui admet pour argument le nombre n d&#039;itération de la fonction, et les coordonnées de 2 points. A chaque itération, la fonction calcule pour chaque segment, un nouveau point et le relie ensuite aux deux autres.&lt;br /&gt;
&lt;br /&gt;
On obtient en tout 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; segments entremêlés, qui forment un dragon.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s go !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec dragon (n:int) (a:int) (b:int) (c:int) (d:int) : unit =&lt;br /&gt;
if (n = 0) then (moveto a b ; lineto c d)&lt;br /&gt;
               else begin&lt;br /&gt;
                      let x = (a+c+d-b)/2 in&lt;br /&gt;
                      let y = (b+d+a-c)/2 in&lt;br /&gt;
                      dragon (n-1) a b x y ;&lt;br /&gt;
                      dragon (n-1) c d x y&lt;br /&gt;
                    end ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Rq : &#039;&#039;&#039; votre version du dragon est bien, mais pas très précises. (Je chipote un peu...)  Pour les paramètres (&amp;lt;tt&amp;gt;dragon 11 100 100 400 400&amp;lt;/tt&amp;gt;), de nombreux carrés ne sont pas bien tracés.&lt;br /&gt;
:Comment expliquez-vous cela, et comment pouvez-vous le corriger ?&lt;br /&gt;
&lt;br /&gt;
::Pour améliorer la précision je suggère de passer les coordonnées en type Float. --[[Utilisateur:Nicolas|Nicolas]] 31 janvier 2009 à 11:42 (CET)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD2==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exercice 1 : Tuples&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 4 :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
On définit la fonction curry par:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let curry (f: &#039;a * &#039;b -&amp;gt; &#039;c) : &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;c&lt;br /&gt;
     = fun x y -&amp;gt; f(x,y);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ou encore en simplifiant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let curry f x y = f(x,y);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On définit ensuite la fonction uncurry par:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry (f: &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;c) : &#039;a * &#039;b -&amp;gt; &#039;c&lt;br /&gt;
     = fun x -&amp;gt; f (fst x) (snd x);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ou encore de trois autres manières plus simplifiées:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = fun x -&amp;gt; f (fst x) (snd x);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = fun x -&amp;gt; match x with (a,b) -&amp;gt; f a b;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = function (a,b) -&amp;gt; f a b;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Avantage de la première forme (à plusieurs arguments): Elle permet une application partielle: on peut appliquer cette fonction à une seule partie des arguments.&lt;br /&gt;
&lt;br /&gt;
Inconvénients de la seconde forme (à un argument): &lt;br /&gt;
*il faut faire appel à fst, snd;&lt;br /&gt;
*Caml doit séparer les paires: c&#039;est une perte de temps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 5 :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
D&#039;après la fonction récursive Fibonacci définit par &amp;lt;br /&amp;gt;&lt;br /&gt;
f(0)=0 &amp;lt;br /&amp;gt;&lt;br /&gt;
f(1)=1 &amp;lt;br /&amp;gt;&lt;br /&gt;
f(n+2)=f(n+1)+f(n), &amp;lt;br /&amp;gt;&lt;br /&gt;
comment compter le nombre d&#039;appels récursifs en Caml? &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* la fonction renvoie une valeur de type int*int :&lt;br /&gt;
  - la première composante est la valeur de Fibonacci pour n,&lt;br /&gt;
  - la seconde composante est le nonbre d&#039;appels recursifs effectués *)&lt;br /&gt;
 let rec fib n =&lt;br /&gt;
     if (n&amp;lt;2) then (n,0)&lt;br /&gt;
     else let t = fib (n-1) in&lt;br /&gt;
          let s = fib (n-2) in &lt;br /&gt;
     (fst t + fst s , snd t + snd s + 1)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&#039;&#039;exemple : &#039;&#039;fib 10 = (55, 88) pour exécuter la fonction Fibonacci(10), il y a 88 appels récursifs nécessaires...&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exercice 2 : Listes&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 5 :&#039;&#039;&#039;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
suite à l&#039;étude des fonctions &lt;br /&gt;
*longueur&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec longueur l =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; 0&lt;br /&gt;
     | _::l -&amp;gt; 1 + longueur l&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*applique&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec app f p =&lt;br /&gt;
     match p with &lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
     | a :: p -&amp;gt; f(a) :: app f p&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*concatene&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec cat l1 l2 =&lt;br /&gt;
     match l1 with&lt;br /&gt;
     [] -&amp;gt; l2&lt;br /&gt;
     | a :: l -&amp;gt; a :: (cat l l2)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*renverse,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec renverse l =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
     | a :: l -&amp;gt; (renverse l) @ [a]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
on remarque des similitudes. Ces fonctions ont le même schéma de base. On peut résumer le principe commun dans la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec reduit l o f =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; o&lt;br /&gt;
     | a :: l -&amp;gt; let appel_rec = reduit l o f in&lt;br /&gt;
                 f a appel_rec&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&#039;&#039;NB :&#039;&#039; le type de &amp;lt;tt&amp;gt;reduit&amp;lt;/tt&amp;gt; donné par Caml est : &amp;lt;tt&amp;gt;val reduit : &#039;a list -&amp;gt; &#039;b -&amp;gt; (&#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b) -&amp;gt; &#039;b = &amp;lt;fun&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 6 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
Reprogrammons les fonctions précédentes à partir de la fonction reduit ! &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let longueur l =&lt;br /&gt;
     let f _ r = 1 + r in &lt;br /&gt;
     reduit l 0 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let app g l =&lt;br /&gt;
     let f a r = (g a)::r in&lt;br /&gt;
     reduit l [] f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let cat l1 l2 =&lt;br /&gt;
     let f a r = a :: r in  &lt;br /&gt;
     reduit l1 l2 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut également introduire la fonction directement avec un &amp;lt;tt&amp;gt;fun&amp;lt;/tt&amp;gt; de la maniere suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let renverse l = reduit l [] (fun a r -&amp;gt; r @ [a])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 7 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le type de la fonction reduit est: ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b ) -&amp;gt; &#039;a list &amp;lt;br/&amp;gt;&lt;br /&gt;
Celui de la fonction List.fold_right est: ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b ) -&amp;gt; &#039;a list -&amp;gt; &#039;b -&amp;gt; &#039;b  ;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
l&#039;ordre des arguments de fold_right est le même que l&#039;ordre des arguments de reduit. La fonction fold_right compte juste deux arguments supplémentaires.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 8 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici la fonction fold_left:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let rec fold_left f b l=&lt;br /&gt;
      match l with&lt;br /&gt;
        []-&amp;gt;b&lt;br /&gt;
       |a::l -&amp;gt; fold_left f (f b a) l;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Cette fonction est &#039;&#039;récursive terminale&#039;&#039;, de type ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;a ) -&amp;gt; &#039;a -&amp;gt; &#039;b list -&amp;gt; &#039;a .&lt;br /&gt;
&lt;br /&gt;
==Le TP1 - début==&lt;br /&gt;
&lt;br /&gt;
Le sujet [http://www.lama.univ-savoie.fr/~hyvernat/Enseignement/0809/info401/tp1.pdf programmes récursifs, listes], au format pdf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 1 : Quelques compléments sur les programmes récursifs&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans cette partie, on travaille sur la fonction Fibonacci&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On commence par l&#039;utiliser sous la forme :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib n =&lt;br /&gt;
if n&amp;lt;2&lt;br /&gt;
   then n&lt;br /&gt;
   else fib (n-1) + fib (n-2)&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comprendre ce qu&#039;il se passe, on trace la fonction à l&#039;aide de &amp;quot;#trace&amp;quot; pour fib 5&lt;br /&gt;
&lt;br /&gt;
fib &amp;lt;-- n veut dire que l&#039;on donne la valeur n à la fonction fib&lt;br /&gt;
&lt;br /&gt;
alors que fib --&amp;gt; n veut dire que fib renvoie n&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib 5 ;;&lt;br /&gt;
fib &amp;lt;-- 5&lt;br /&gt;
fib &amp;lt;-- 3&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib &amp;lt;-- 2&lt;br /&gt;
fib &amp;lt;-- 0&lt;br /&gt;
fib --&amp;gt; 0&lt;br /&gt;
...&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib &amp;lt;-- 2&lt;br /&gt;
fib &amp;lt;-- 0&lt;br /&gt;
fib --&amp;gt; 0&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib --&amp;gt; 2&lt;br /&gt;
fib --&amp;gt; 3&lt;br /&gt;
fib --&amp;gt; 5&lt;br /&gt;
- : int = 5&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut remarquer que la fonction calcule plusieurs fois le même fib n.&lt;br /&gt;
Une optimisation consisterait à garder certaines valeurs en mémoire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On écrit fib2 de type &amp;quot;int -&amp;gt; int*int&amp;quot; qui renvoie le valeur de fib n (fst fib2 n) et fib n-1 (snd (fib2 n)) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib2 n = &lt;br /&gt;
if n&amp;lt;2 &lt;br /&gt;
   then (n,n-1)&lt;br /&gt;
   else let t = fib2 (n-1) in&lt;br /&gt;
      (fst(t)+snd(t),fst(t));;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 3&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comparer les fonctions fib et fib2, on les trace pour n=7 :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib 7 ;;&lt;br /&gt;
fib &amp;lt;-- 7&lt;br /&gt;
fib &amp;lt;-- 5&lt;br /&gt;
fib &amp;lt;-- 3&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
...&lt;br /&gt;
fib --&amp;gt; 3&lt;br /&gt;
fib --&amp;gt; 5&lt;br /&gt;
fib --&amp;gt; 8&lt;br /&gt;
fib --&amp;gt; 13&lt;br /&gt;
- : int = 13&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib2 7 ;;&lt;br /&gt;
fib2 &amp;lt;-- 7&lt;br /&gt;
fib2 &amp;lt;-- 6&lt;br /&gt;
fib2 &amp;lt;-- 5&lt;br /&gt;
fib2 &amp;lt;-- 4&lt;br /&gt;
fib2 &amp;lt;-- 3&lt;br /&gt;
fib2 &amp;lt;-- 2&lt;br /&gt;
fib2 &amp;lt;-- 1&lt;br /&gt;
fib2 --&amp;gt; (1, 0)&lt;br /&gt;
fib2 --&amp;gt; (1, 1)&lt;br /&gt;
fib2 --&amp;gt; (2, 1)&lt;br /&gt;
fib2 --&amp;gt; (3, 2)&lt;br /&gt;
fib2 --&amp;gt; (5, 3)&lt;br /&gt;
fib2 --&amp;gt; (8, 5)&lt;br /&gt;
fib2 --&amp;gt; (13, 8)&lt;br /&gt;
- : int * int = (13, 8)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On remarque que fib2 fait 14 calculs alors que fib en 81 pour n=7.&lt;br /&gt;
Afin de retourner uniquement la valeur de fib n on définit une nouvelle fonction, beaucoup plus rapide que fib, &lt;br /&gt;
en prenant le premier élément de la paire constituant fib2 n :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let fib n = fst ( fib2 n ) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 4 ( Bonus )&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On veut créer fib3 de type int-&amp;gt;int-&amp;gt;int-&amp;gt;int tel que :&lt;br /&gt;
&lt;br /&gt;
- son premier argument est l&#039;entier n pour fibonacci de n&lt;br /&gt;
&lt;br /&gt;
- les 2 autres arguments sont des accumulateurs qui permettent de conserver des valeurs successives ( pour i-1 et i )&lt;br /&gt;
&lt;br /&gt;
 --- à venir ---&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 2 : Manipulation des listes&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici quelque fonctions définies en utilisant &amp;lt;tt&amp;gt;List.fold_right&amp;lt;/tt&amp;gt; :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let longueur l = let f a r = 1 + r in List.fold_right f l 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let app f l = let f&#039; a r = ( f a )::r in List.fold_right f&#039; l []&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let concat l1 l2 = let f a r = a::r in List.fold_right l1 l2 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici la fonction reverse telle qu&#039;on l&#039;a écrite dans le TD&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec reverse l = &lt;br /&gt;
  match l with&lt;br /&gt;
  []-&amp;gt;[]&lt;br /&gt;
  |a::l -&amp;gt; (reverse l)@[a] ;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour la comparer avec la fonction &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; de Caml, on va regarder le temps d&#039;exécution sur une très grande liste.&lt;br /&gt;
&lt;br /&gt;
Pour cela, on créé une fonction qui fabrique une liste de n valeurs :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec longueliste  n = &lt;br /&gt;
  if n=0 &lt;br /&gt;
  then []&lt;br /&gt;
  else n::longueliste (n-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut tester les fonctions avec une liste de 10000 éléments.&lt;br /&gt;
&lt;br /&gt;
La fonction &amp;lt;tt&amp;gt;reverse&amp;lt;/tt&amp;gt; met environ 15s alors que &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; s&#039;exécute immédiatement.&lt;br /&gt;
&lt;br /&gt;
Cela montre donc que &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; est bien plus efficace que &amp;lt;tt&amp;gt;reverse&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::En fait, reverse fait ( n + n-1 + n-2 + ... + 1 ) opérations à chaque fois (il met le premier élément au bout de la liste et ainsi de suite) , soit au total &amp;lt;math&amp;gt;n*(n+1)/2 \sim n^2&amp;lt;/math&amp;gt; opérations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; utilise la fonction suivante :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec rev_append l1 l2 =&lt;br /&gt;
  match l1 with&lt;br /&gt;
    [] -&amp;gt; l2&lt;br /&gt;
  | a::l -&amp;gt; rev_append l (a::l2);;&lt;br /&gt;
&lt;br /&gt;
let rec rev l = rev_append l [];;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Elle fait donc environ &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; opérations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 3 : Deux algorithmes de tri pour les listes&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On programme une fonction d&#039;insertion qui permet d&#039;insérer un élément à sa place&lt;br /&gt;
dans une liste triée.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insertion n l =&lt;br /&gt;
  match l with&lt;br /&gt;
    [] -&amp;gt; [n]&lt;br /&gt;
  | a::l&#039; -&amp;gt; if n&amp;lt;=a&lt;br /&gt;
             then n::l&lt;br /&gt;
             else a::(insertion n l&#039;) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On programme ensuite le tri par insertion.&lt;br /&gt;
&lt;br /&gt;
Le tri par insertion fonctionne de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
- la liste vide est triée,&lt;br /&gt;
&lt;br /&gt;
- pour trier la liste &amp;quot;&amp;lt;tt&amp;gt;a::l&amp;lt;/tt&amp;gt;&amp;quot;, on commence par trier (récursivement) la liste &amp;lt;tt&amp;gt;l&amp;lt;/tt&amp;gt;, puis on insère&lt;br /&gt;
l&#039;élément &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; dans le résultat.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec tri_insertion l =&lt;br /&gt;
 match l with&lt;br /&gt;
    [] -&amp;gt; []&lt;br /&gt;
  | a::l&#039; -&amp;gt; insertion a (tri_insertion l&#039;) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ou plus simplement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let tri l = List.fold.right insertion l [] ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 3&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Maintenant, on programme une fonction fusionne qui permet de fusionner deux listes triées en une seule liste triée.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionne l1 l2 =&lt;br /&gt;
  match l1 with &lt;br /&gt;
     [] -&amp;gt; l2&lt;br /&gt;
   | a::l&#039; -&amp;gt; begin&lt;br /&gt;
                match l2 with&lt;br /&gt;
                   [] -&amp;gt; l1&lt;br /&gt;
                 | b::l&#039;&#039; -&amp;gt; if a&amp;lt;=b then ( a::fusionne l&#039; l2 ) &lt;br /&gt;
                                     else ( b::fusionne l1 l&#039;&#039;) &lt;br /&gt;
&lt;br /&gt;
              end;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour éviter d&#039;imbriquer des &amp;quot;match&amp;quot;, on peut aussi filtrer directement la paire &amp;lt;tt&amp;gt;(l1,l2)&amp;lt;/tt&amp;gt; et regrouper les cas d&#039;un des listes vides ensemble : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionnebis l1 l2 =&lt;br /&gt;
  match l1,l2 with&lt;br /&gt;
      [],l | l,[]  -&amp;gt;  l&lt;br /&gt;
    | (a::l&#039;, b::l2&#039;)  -&amp;gt; &lt;br /&gt;
        if a &amp;lt;= b&lt;br /&gt;
        then a::(fusionnebis l&#039; l2)&lt;br /&gt;
        else b::(fusionnebis l1 l2&#039;)  ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 4&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis une fonction sépare qui permet de séparer une liste quelconque en&lt;br /&gt;
deux listes de taille équivalente&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec separe l =&lt;br /&gt;
  match l with&lt;br /&gt;
     [] -&amp;gt; ([],[])&lt;br /&gt;
   | [a] -&amp;gt; ([a],[])&lt;br /&gt;
   | a::b::l&#039; -&amp;gt; let t=separe l&#039; in (a::(fst t),b::(snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 5&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On doit maintenant programmer un deuxième type de tri : le tri par fusion.&lt;br /&gt;
&lt;br /&gt;
Le tri fusion fonctionne de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
- la liste vide est triée,&lt;br /&gt;
&lt;br /&gt;
- pour trier une liste non-vide, on sépare la liste en deux parties de longueur égale (à un&lt;br /&gt;
élément prêt), on trie (récursivement) ces deux listes, puis on fusionne les deux résultats.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec tri_fusion l =  &lt;br /&gt;
  match l with&lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
   | [a] -&amp;gt; [a]&lt;br /&gt;
   | _ -&amp;gt; let t=separe l in&lt;br /&gt;
          fusionne (tri_fusion (fst t)) (tri_fusion (snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 6&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comparer l&#039;efficacité des deux fonctions de tri, on utilise la même méthode que précédemment : &lt;br /&gt;
&lt;br /&gt;
On créé a l&#039;aide d&#039;un fonction une liste aléatoire de 10000 éléments, les éléments étant non triés.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let liste_aleatoire n =&lt;br /&gt;
  let rec aux n max = &lt;br /&gt;
    if n=0&lt;br /&gt;
    then []&lt;br /&gt;
    else (Random.int max)::aux (n-1) max&lt;br /&gt;
  in&lt;br /&gt;
  aux n n ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite on trie cette liste avec les deux fonctions.&lt;br /&gt;
&lt;br /&gt;
Le tri_fusion renvoie instantanément une liste de 10000 éléments aléatoires triés. &lt;br /&gt;
&lt;br /&gt;
Le tri insertion, quant à lui, prend plus d&#039;une dizaine de secondes.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;Remarque :&#039;&#039; cela vient du fait que le tri fusion divise la taille de la liste par deux à chaque étape, alors que le tri par insertion soustrait un élément à chaque étape.&lt;br /&gt;
: On peut montrer que le temps de calcul pour le tri fusion est proportionnel à &amp;lt;math&amp;gt;n \log(n)&amp;lt;/math&amp;gt;, ce qui est très petit par rapport à &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt; (temps d&#039;execution moyen du tri par insertion) quand &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; est grand.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 7&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On souhaite trier une liste selon la hauteur des points c&#039;est-à-dire selon le deuxième élément de la paire de flottants.&lt;br /&gt;
Pour cela, il faudrait faire un tri fusion sur le 2eme élément de la paire représentant les points&lt;br /&gt;
tout en sauvegardant le 1er élément...&lt;br /&gt;
&lt;br /&gt;
On peut créer une fonction de tri par fusion générale, qui prend comme paramètre une autre fonction (qui sert à vérifier la comparaison de 2 éléments et rend true ou false) afin de choisir le tri que l&#039;on veut ( décroissant, croissant ... ) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionne comp l1 l2 =&lt;br /&gt;
 match (l1,l2) with&lt;br /&gt;
    ([],_) -&amp;gt; l2&lt;br /&gt;
  | (_,[]) -&amp;gt; l1&lt;br /&gt;
  | (a::l&#039;, b::l2&#039;) -&amp;gt; &lt;br /&gt;
     if (comp a b)&lt;br /&gt;
     then a::(fusionne l&#039; l2)&lt;br /&gt;
     else b::(fusionne l1 l2&#039;);;&lt;br /&gt;
&lt;br /&gt;
let rec tri_fusion comp l =  &lt;br /&gt;
 match l with&lt;br /&gt;
    [] -&amp;gt; []&lt;br /&gt;
  | [a] -&amp;gt; [a]&lt;br /&gt;
  | _ -&amp;gt; let t=separe l in&lt;br /&gt;
         fusionne comp (tri_fusion comp (fst t)) (tri_fusion comp (snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il suffit alors a l&#039;utilisateur de définir la fonction de comparaison pour ensuite faire appel à &amp;lt;tt&amp;gt;tri_fusion&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Par exemple, pour trier dans un ordre décroissant :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let dec a n  = if a&amp;gt;=n then true&lt;br /&gt;
else false ;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
ou même plus simplement&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let dec = (&amp;gt;=) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour trier une liste de paires, il faut créer une fonction qui compare les seconds membres ;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let paire a n  = (snd a) &amp;lt;= (snd n)  ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ici, les paires seront triées selon le second membre dans l&#039;ordre croissant.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 8 ( Bonus )&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un algorithme de tri est dit stable quand il ne modifie pas l&#039;ordre relatifs des éléments &amp;quot;égaux&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Par exemple, on tri par ordre croissant du premier membre une liste de paires de float : [ ( 5 , 3 ) ; ( -2 , 8 ) ; ( -2 , 2 ) ; ( 5 , 8 ) ; ( 5 , -8 ) ]  &lt;br /&gt;
&lt;br /&gt;
non stable : &amp;lt;tt&amp;gt;[(-2, 2); (-2, 8); (5, -8); (5, 8); (5, 3)]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
stable : &amp;lt;tt&amp;gt;[(-2, 8); (-2, 2); (5, 3); (5, 8); (5, -8)]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour qu&#039;un tri soit stable, la comparaison de deux éléments doit comprendre aussi le &amp;quot;=&amp;quot;, comme c&#039;est le cas pour les fonctions paire et dec.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD3==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Exercice 1 : les arbres binaires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt; Question 1 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type &#039;a arbre = Vide | Noeud of &#039;a*&#039;a arbre*&#039;a arbre ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 2 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
let rec taille a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; 1 + (taille g) + (taille d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction taille compte le nombre de noeuds que contient un arbre.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 3 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec applique f a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; Vide&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; Noeud(f e,applique f g,applique f d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction applique est équivalente à la fonction List.map&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 4 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec poids (f : &#039;a -&amp;gt; int) a = &lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; (f e) + (poids f g) + (poids f d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 5 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec reduit a o f =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; let x = reduit g o f in&lt;br /&gt;
       			let y = reduit d o f in&lt;br /&gt;
                        f e x y ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction reduit est equivalente à la fonction List.fold_right pour le type des arbres.&lt;br /&gt;
&lt;br /&gt;
Réécriture de taille et poids :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec taille a = reduit a 0 (fun e x y -&amp;gt; 1 + x + y) ;;&lt;br /&gt;
let rec poids f a = reduit a 0 (fun e x y -&amp;gt; (f e) + (f x) + (f y)) ;; (*?????*)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 6 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec collecte a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; []&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; e::(collecte g)@(collecte d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction collecte récupère tous les éléments de l&#039;arbre et les renvoie sous forme d&#039;une liste.&lt;br /&gt;
&lt;br /&gt;
Avec la fonction reduit :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec collecte a = reduit a [] (fun e x y -&amp;gt; e::x@y) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 7 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec feuilles a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; []&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; if (g=Vide &amp;amp;&amp;amp; d=Vide) then [e]&lt;br /&gt;
       			else (feuilles g)@(feuilles d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Avec reduit :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec feuilles a = reduit a [] (fun e x y -&amp;gt; if (x=[] &amp;amp;&amp;amp; y=[]) then [e]&lt;br /&gt;
					       else x@y) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Exercice 2 : la tortue &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt; Question 1 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type action = Forward of int | Left of int | SetPos of int*int | SetHeading of int | PenUp | Pendown ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 2 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
let rec ecrit (l:action list) (pen:bool) : bool =&lt;br /&gt;
   match l with&lt;br /&gt;
    	[] -&amp;gt; false&lt;br /&gt;
       |(Forward d)::l -&amp;gt; if (d=0 || pen=false) then ecrit l pen&lt;br /&gt;
                          else true &lt;br /&gt;
       |PenUp::l -&amp;gt; ecrit l false&lt;br /&gt;
       |PenDown::l -&amp;gt; ecrit l true&lt;br /&gt;
       | _ -&amp;gt; ecrit l pen ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction ecrit renvoie true si la tortue écrit qqch ou false sinon.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 3 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec pos (x:int) (y:int) (a:int) (l:action list) : ((int*int)int) =&lt;br /&gt;
   match l with&lt;br /&gt;
    	[] -&amp;gt; ((x,y),a)&lt;br /&gt;
       |PenUp::l |Pendown::l -&amp;gt; pos x y a l&lt;br /&gt;
       |(Left b)::l -&amp;gt; pos x y (a+b) l&lt;br /&gt;
       |(SetPos(x&#039;,y&#039;))::l -&amp;gt; pos x&#039; y&#039; a l&lt;br /&gt;
       |(SetHeading b)::l -&amp;gt; pos x y b l &lt;br /&gt;
       |(Forward d)::l -&amp;gt; pos (x+(sin a)*d) (y+(cos a)*d) a l ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 5 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type action = Forward of int | SetPos of int*int | SetHeading of int | Left of int | PenUp | Pendown | Repeat of int*action list ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD4==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 1 : Petits exercices combinatoires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On commence par créer une fonction intermédiaire.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supp&#039; x l =&lt;br /&gt;
   match l with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |b::f&#039;-&amp;gt; if (x=b) then supp&#039; x l&#039;&lt;br /&gt;
                        else b::supp&#039; x f&#039;;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supp l =&lt;br /&gt;
   match l with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |a::l&#039;-&amp;gt; a::supp supp&#039; a l&#039;;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 2 : Dictionnaires &amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Un dictionnaire est une liste de paires&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Question 2 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insere c v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[(c,v)]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (c=c&#039;) then (c&#039;,v&#039;)::(insere c v d)&lt;br /&gt;
                               else (c,v)::d ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supprime c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (c=c&#039;) then d&lt;br /&gt;
                               else (c&#039;,v&#039;)::(supprime c d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec existe_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; false&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; (c=c&#039;) || existe_cle c d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec existe_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; false&lt;br /&gt;
      |(_,v&#039;)::d -&amp;gt; if (v=v&#039;) then true&lt;br /&gt;
                              else existe_val v d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec recherche_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; None&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; if (c=c&#039;) then Some c&#039;&lt;br /&gt;
                              else recherche_cle c d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* liste des valeurs de c par on peut avoir plusieurs cases, et donc plusieurs clés, avec une même valeur *)&lt;br /&gt;
let rec recherche_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (v=v&#039;) then c&#039;::(recherche_val v d)&lt;br /&gt;
                              else recherche_val v d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Liste des clés *)&lt;br /&gt;
let rec liste_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; []&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; c&#039;::(liste_cle c d);;&lt;br /&gt;
&lt;br /&gt;
(* Liste des valeurs *)&lt;br /&gt;
let rec liste_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(_,v&#039;)::d -&amp;gt; v&#039;::(liste_val v d);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut également utiliser des fonctions existantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Liste des clés *)&lt;br /&gt;
let liste_cle d = List.map fst;;&lt;br /&gt;
&lt;br /&gt;
(* Liste des valeurs, attention aux doublons! *)&lt;br /&gt;
let liste_val d = suppr_doublons(List.map snd);;&lt;br /&gt;
  &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 4 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec zip l1 l2&lt;br /&gt;
   match l1 l2 with&lt;br /&gt;
      [].[]-&amp;gt;[]&lt;br /&gt;
      |c::lc, v::lv -&amp;gt; (c,v)::(zip lc lv)&lt;br /&gt;
      |_,_ -&amp;gt; [];;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 5 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On aurait pu utiliser une liste triée : si par exemple on cherche 12 et qu&#039;on en est à 14 dans la liste, on sait que 12 n&#039;y est pas. PB : ceci n&#039;empêche pas d&#039;aller à la fin de la liste si la valeur ou la clé recherchée est grande ... &amp;lt;br/&amp;gt;&lt;br /&gt;
Une recherche dichotomique est inefficace sur les listes ... &amp;lt;br/&amp;gt;&lt;br /&gt;
   =&amp;gt; dans la bibliothèque hash table de Caml, il existe un List.zip&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 3 : Arbres binaires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Question 1 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
La profondeur d&#039;un arbre binaire correspond au nombre d&#039;étage : on regarde à partir de la première racine et des sous arbres, on calcule la profondeur à gauche et la profondeur à droite, on prend la plus grande et on y ajoute 1. &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec profondeur a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; 0&lt;br /&gt;
      |Noeud(_,g,d) -&amp;gt; 1 + max(profondeurg) (profondeurd);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 2 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec equilibre a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; true&lt;br /&gt;
      |Noeud(_,g,d) -&amp;gt; if (profondeur g)=(profondeur d) || (profondeur g)=(profondeur d +1) || (profondeur g +1)=(profondeur d)&lt;br /&gt;
                          then (equilibre d)&amp;amp;&amp;amp;(equilibre g)&lt;br /&gt;
                          else false;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec present e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; false&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; e&#039;=e || present e g || present e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 4 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec present e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; false&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; if (e&#039;=e) then true&lt;br /&gt;
                                  else  if (e&amp;lt;e&#039;) then present e g&lt;br /&gt;
                                                  else present e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 5 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insere e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; e&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; if (e&amp;lt;e&#039;) then insere e g&lt;br /&gt;
                                  else insere e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Le TP2==&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt;Partie 1&amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
QUESTION 1 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction suivante permet de calculer les ensemble de nombre. Elle est réalisé à l&#039;aide d&#039;une concaténation de la liste précédente avec la liste modifier ainsi que List.map.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
open List&lt;br /&gt;
&lt;br /&gt;
let rec sous_ensemble n=&lt;br /&gt;
    if n=0&lt;br /&gt;
    then &lt;br /&gt;
      [[]]&lt;br /&gt;
    else&lt;br /&gt;
      let liste = sous_ensemble (n-1) in (List.map (fun l-&amp;gt;n::l) liste) @ liste&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
QUESTION 2 :&amp;lt;br/&amp;gt;&lt;br /&gt;
la fonction supprime doublon est réalisé tout d&#039;abord en triant la liste puis en regardant si deux éléments concécutif sont les mêmes, si oui on en supprime un.&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec lstTrier liste=&lt;br /&gt;
  match liste with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
    | [a]-&amp;gt;liste&lt;br /&gt;
    | a::b::liste-&amp;gt;if a=b then lstTrier (a::liste)&lt;br /&gt;
                          else a::lstTrier (b::liste)&lt;br /&gt;
&lt;br /&gt;
let supprime_doublon lst=&lt;br /&gt;
 lstTrier (List.sort (-) lst)&lt;br /&gt;
&amp;lt;/source&amp;gt; &lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt;Partie 2&amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
QUESTION &lt;br /&gt;
&lt;br /&gt;
==Contrôle continu 1==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TP3==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD5==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TP4==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==TD6==&lt;/div&gt;</summary>
		<author><name>Laurent corantin</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=INFO401_corr_TD_TP&amp;diff=4144</id>
		<title>INFO401 corr TD TP</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=INFO401_corr_TD_TP&amp;diff=4144"/>
		<updated>2009-04-28T13:00:12Z</updated>

		<summary type="html">&lt;p&gt;Laurent corantin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Préliminaires==&lt;br /&gt;
&lt;br /&gt;
Pour afficher correctement dans le wiki, allez voir un peu comment on fait. Vous pouvez regarder par exemple sur le [[INFO401 | wiki du cours]] ou directement sur des articles de [http://fr.wikipedia.org/wiki/Accueil Wikipedia]. La documentation de mediawiki se trouve [http://meta.wikimedia.org/wiki/Aide:Éditeur ici].&lt;br /&gt;
&lt;br /&gt;
Un truc important : pour rentrer du code Caml, il faut mettre les balises &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;...&amp;lt;/source&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; autour de votre code. Allez par exemple voir le début de la section sur [[#Le TD1 et le TP0 | le TD1 et TP0]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vous pouvez aller discuter des corrections dans les sujets de discussions associes...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD1 et le TP0==&lt;br /&gt;
&lt;br /&gt;
Pour vous montrer un exemple de ce que j&#039;attends, voila la correction de la fonction factorielle. (C&#039;était facile...) J&#039;ai volontairement mis beaucoup de commentaires...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;La fonction factorielle (TD1, exercice 2, question 2)&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but est de calculer la fonction &amp;lt;math&amp;gt;!n = 1\times2\times \cdots \times n&amp;lt;/math&amp;gt; par récurrence. La version typée est verbeuse de la fonction correspondante en Caml donne :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* fonction factorielle : c&#039;est la factorielle habituelle des mathématiciens... *)&lt;br /&gt;
let rec fact (n:int) : int =&lt;br /&gt;
  if (n&amp;gt;1)&lt;br /&gt;
  then  n * (fact (n-1))&lt;br /&gt;
  else 1      (* rq : pour que le programme ne boucle pas sur les valeurs négatives, on renvoie 1 dés que n&amp;lt;1 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme la fonction est récursive, il ne faut pas oublier le &amp;lt;tt&amp;gt;rec&amp;lt;/tt&amp;gt; au début de la définition.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On aurait pu faire une autre version, qui fonctionne différemment sur les nombres négatifs :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fact&#039; = function&lt;br /&gt;
   n when (n&amp;gt;0) -&amp;gt; n * fact&#039; (n-1)&lt;br /&gt;
 | n when (n&amp;lt;0) -&amp;gt; n * fact&#039; (n+1)&lt;br /&gt;
 | _ -&amp;gt; 1  (* si n n&#039;est ni plus petit que 0 ni plus grand que 0, n est égal à 0, et on renvoie donc 1 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;ai volontairement mis une version qui contient plusieurs choses que nous n&#039;avons pas encore vues en cours :&lt;br /&gt;
* utilisation de &amp;quot;&amp;lt;tt&amp;gt;function&amp;lt;/tt&amp;gt;&amp;quot; plutôt que &amp;lt;tt&amp;gt;fun&amp;lt;/tt&amp;gt;,&lt;br /&gt;
* le symbole &amp;quot;&amp;lt;tt&amp;gt;|&amp;lt;/tt&amp;gt;&amp;quot;,&lt;br /&gt;
* le mot clé &amp;quot;&amp;lt;tt&amp;gt;when&amp;lt;/tt&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Vous devriez pouvoir comprendre ce que fait la fonction. Sinon, voici une version que vous auriez pu écrire :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fact_bis = fun n -&amp;gt;&lt;br /&gt;
  if (n=0)&lt;br /&gt;
  then 1&lt;br /&gt;
  else begin&lt;br /&gt;
    if (n&amp;gt;0)&lt;br /&gt;
    then n*fact_bis (n-1)&lt;br /&gt;
    else n*fact_bis (n+1)   (* dans ce cas, n est forcement négatif *)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Les fonctions sommes &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il s&#039;agit ici d&#039;écrire la fonction qui va additionner les carrés des entiers de 1 jusqu&#039;à un nombre donné.&lt;br /&gt;
&lt;br /&gt;
Cela donne :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_carre b =&lt;br /&gt;
if (b=0) then 0&lt;br /&gt;
else (b*b) + somme_carre (b-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite on nous demande de calculer la somme des cubes des entiers de 1 jusqu&#039;à un nombre donné. On pourrait faire le même programme en remplaçant b*b par b*b*b, mais on va définir une fonction puissance (car elle n&#039;existe pas d&#039;origine sous Caml), qui nous servira aussi pour la suite... :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec puissance x a =&lt;br /&gt;
if (a = 0) then 1&lt;br /&gt;
else x * puissance x (a-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On doit maintenant calculer la somme des &amp;lt;math&amp;gt;i^i&amp;lt;/math&amp;gt;, i variant de 1 à un nombre donné :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_puissance b =&lt;br /&gt;
if (b=0) then 0&lt;br /&gt;
else (puissance b b) + somme_puissance (b-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut définir une unique fonction qui permettrait de faire toutes ces sommes, celle-ci aura pour argument une fonction quelconque :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_fonction n f = (* f étant une fonction *)&lt;br /&gt;
if (n=0) then f 0&lt;br /&gt;
else f n + somme_fonction (n-1) f;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
cette fonction est de type &amp;quot;&amp;lt;tt&amp;gt;int -&amp;gt; fun -&amp;gt; int&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Nombres pairs et impairs (TP0 Partie 2 Question 2) &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut écrire les fonctions récursives pairs et impairs, qui renvoient vrai si le nombre est pair (respectivement impair) et faux si le nombre est impair (respectivement pair);&lt;br /&gt;
Ici nous devons déclarer simultanément les deux fonctions, car chacune fait appel à l&#039;autre lors de son exécution.&lt;br /&gt;
&lt;br /&gt;
Cela donne :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec pair n =&lt;br /&gt;
  if (n=0) then true&lt;br /&gt;
  else impair (n-1)&lt;br /&gt;
and impair n =&lt;br /&gt;
  if (n=0) then false&lt;br /&gt;
  else  pair (n-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Suite de Fibonacci &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La suite de fibonacci est tel que u&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;=0 u&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;=1 et u&amp;lt;sub&amp;gt;n+2&amp;lt;/sub&amp;gt;=u&amp;lt;sub&amp;gt;n+1&amp;lt;/sub&amp;gt;+u&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib n =&lt;br /&gt;
if (n=0) then 0&lt;br /&gt;
else if (n=1) then 1&lt;br /&gt;
else fib (n-1) + fib (n-2);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La plus grande valeur que l&#039;on peut obtenir sans que cela soit trop long est 24157817, ce qui correspond à fib 37.&lt;br /&gt;
Nous trouvons qu&#039;il faut déjà 88 additions pour calculer fib 10.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Rq :&#039;&#039;&#039; fib de 37 prend effectivement beaucoup de temps. Il faut 39088168 additions avant d&#039;en arriver à bout. Il est possible de faire une version de Fibonacci qui va très vite et qui calcule &amp;lt;tt&amp;gt;fib 37&amp;lt;/tt&amp;gt; en seulement 36 additions...&lt;br /&gt;
: Comment ?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Dragon ! &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;i&amp;gt; Le dragon est une créature mythique, présente dans de nombreuses cultures.&lt;br /&gt;
  On peut déterminer deux grands types de dragons : le dragon occidental et le dragon oriental&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction dragon a pour but de dessiner un dragon, pour cela on utilise une fonction récursive qui admet pour argument le nombre n d&#039;itération de la fonction, et les coordonnées de 2 points. A chaque itération, la fonction calcule pour chaque segment, un nouveau point et le relie ensuite aux deux autres.&lt;br /&gt;
&lt;br /&gt;
On obtient en tout 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; segments entremêlés, qui forment un dragon.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s go !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec dragon (n:int) (a:int) (b:int) (c:int) (d:int) : unit =&lt;br /&gt;
if (n = 0) then (moveto a b ; lineto c d)&lt;br /&gt;
               else begin&lt;br /&gt;
                      let x = (a+c+d-b)/2 in&lt;br /&gt;
                      let y = (b+d+a-c)/2 in&lt;br /&gt;
                      dragon (n-1) a b x y ;&lt;br /&gt;
                      dragon (n-1) c d x y&lt;br /&gt;
                    end ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Rq : &#039;&#039;&#039; votre version du dragon est bien, mais pas très précises. (Je chipote un peu...)  Pour les paramètres (&amp;lt;tt&amp;gt;dragon 11 100 100 400 400&amp;lt;/tt&amp;gt;), de nombreux carrés ne sont pas bien tracés.&lt;br /&gt;
:Comment expliquez-vous cela, et comment pouvez-vous le corriger ?&lt;br /&gt;
&lt;br /&gt;
::Pour améliorer la précision je suggère de passer les coordonnées en type Float. --[[Utilisateur:Nicolas|Nicolas]] 31 janvier 2009 à 11:42 (CET)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD2==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exercice 1 : Tuples&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 4 :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
On définit la fonction curry par:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let curry (f: &#039;a * &#039;b -&amp;gt; &#039;c) : &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;c&lt;br /&gt;
     = fun x y -&amp;gt; f(x,y);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ou encore en simplifiant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let curry f x y = f(x,y);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On définit ensuite la fonction uncurry par:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry (f: &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;c) : &#039;a * &#039;b -&amp;gt; &#039;c&lt;br /&gt;
     = fun x -&amp;gt; f (fst x) (snd x);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ou encore de trois autres manières plus simplifiées:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = fun x -&amp;gt; f (fst x) (snd x);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = fun x -&amp;gt; match x with (a,b) -&amp;gt; f a b;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = function (a,b) -&amp;gt; f a b;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Avantage de la première forme (à plusieurs arguments): Elle permet une application partielle: on peut appliquer cette fonction à une seule partie des arguments.&lt;br /&gt;
&lt;br /&gt;
Inconvénients de la seconde forme (à un argument): &lt;br /&gt;
*il faut faire appel à fst, snd;&lt;br /&gt;
*Caml doit séparer les paires: c&#039;est une perte de temps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 5 :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
D&#039;après la fonction récursive Fibonacci définit par &amp;lt;br /&amp;gt;&lt;br /&gt;
f(0)=0 &amp;lt;br /&amp;gt;&lt;br /&gt;
f(1)=1 &amp;lt;br /&amp;gt;&lt;br /&gt;
f(n+2)=f(n+1)+f(n), &amp;lt;br /&amp;gt;&lt;br /&gt;
comment compter le nombre d&#039;appels récursifs en Caml? &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* la fonction renvoie une valeur de type int*int :&lt;br /&gt;
  - la première composante est la valeur de Fibonacci pour n,&lt;br /&gt;
  - la seconde composante est le nonbre d&#039;appels recursifs effectués *)&lt;br /&gt;
 let rec fib n =&lt;br /&gt;
     if (n&amp;lt;2) then (n,0)&lt;br /&gt;
     else let t = fib (n-1) in&lt;br /&gt;
          let s = fib (n-2) in &lt;br /&gt;
     (fst t + fst s , snd t + snd s + 1)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&#039;&#039;exemple : &#039;&#039;fib 10 = (55, 88) pour exécuter la fonction Fibonacci(10), il y a 88 appels récursifs nécessaires...&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exercice 2 : Listes&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 5 :&#039;&#039;&#039;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
suite à l&#039;étude des fonctions &lt;br /&gt;
*longueur&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec longueur l =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; 0&lt;br /&gt;
     | _::l -&amp;gt; 1 + longueur l&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*applique&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec app f p =&lt;br /&gt;
     match p with &lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
     | a :: p -&amp;gt; f(a) :: app f p&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*concatene&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec cat l1 l2 =&lt;br /&gt;
     match l1 with&lt;br /&gt;
     [] -&amp;gt; l2&lt;br /&gt;
     | a :: l -&amp;gt; a :: (cat l l2)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*renverse,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec renverse l =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
     | a :: l -&amp;gt; (renverse l) @ [a]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
on remarque des similitudes. Ces fonctions ont le même schéma de base. On peut résumer le principe commun dans la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec reduit l o f =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; o&lt;br /&gt;
     | a :: l -&amp;gt; let appel_rec = reduit l o f in&lt;br /&gt;
                 f a appel_rec&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&#039;&#039;NB :&#039;&#039; le type de &amp;lt;tt&amp;gt;reduit&amp;lt;/tt&amp;gt; donné par Caml est : &amp;lt;tt&amp;gt;val reduit : &#039;a list -&amp;gt; &#039;b -&amp;gt; (&#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b) -&amp;gt; &#039;b = &amp;lt;fun&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 6 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
Reprogrammons les fonctions précédentes à partir de la fonction reduit ! &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let longueur l =&lt;br /&gt;
     let f _ r = 1 + r in &lt;br /&gt;
     reduit l 0 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let app g l =&lt;br /&gt;
     let f a r = (g a)::r in&lt;br /&gt;
     reduit l [] f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let cat l1 l2 =&lt;br /&gt;
     let f a r = a :: r in  &lt;br /&gt;
     reduit l1 l2 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut également introduire la fonction directement avec un &amp;lt;tt&amp;gt;fun&amp;lt;/tt&amp;gt; de la maniere suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let renverse l = reduit l [] (fun a r -&amp;gt; r @ [a])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 7 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le type de la fonction reduit est: ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b ) -&amp;gt; &#039;a list &amp;lt;br/&amp;gt;&lt;br /&gt;
Celui de la fonction List.fold_right est: ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b ) -&amp;gt; &#039;a list -&amp;gt; &#039;b -&amp;gt; &#039;b  ;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
l&#039;ordre des arguments de fold_right est le même que l&#039;ordre des arguments de reduit. La fonction fold_right compte juste deux arguments supplémentaires.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 8 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici la fonction fold_left:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let rec fold_left f b l=&lt;br /&gt;
      match l with&lt;br /&gt;
        []-&amp;gt;b&lt;br /&gt;
       |a::l -&amp;gt; fold_left f (f b a) l;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Cette fonction est &#039;&#039;récursive terminale&#039;&#039;, de type ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;a ) -&amp;gt; &#039;a -&amp;gt; &#039;b list -&amp;gt; &#039;a .&lt;br /&gt;
&lt;br /&gt;
==Le TP1 - début==&lt;br /&gt;
&lt;br /&gt;
Le sujet [http://www.lama.univ-savoie.fr/~hyvernat/Enseignement/0809/info401/tp1.pdf programmes récursifs, listes], au format pdf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 1 : Quelques compléments sur les programmes récursifs&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans cette partie, on travaille sur la fonction Fibonacci&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On commence par l&#039;utiliser sous la forme :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib n =&lt;br /&gt;
if n&amp;lt;2&lt;br /&gt;
   then n&lt;br /&gt;
   else fib (n-1) + fib (n-2)&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comprendre ce qu&#039;il se passe, on trace la fonction à l&#039;aide de &amp;quot;#trace&amp;quot; pour fib 5&lt;br /&gt;
&lt;br /&gt;
fib &amp;lt;-- n veut dire que l&#039;on donne la valeur n à la fonction fib&lt;br /&gt;
&lt;br /&gt;
alors que fib --&amp;gt; n veut dire que fib renvoie n&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib 5 ;;&lt;br /&gt;
fib &amp;lt;-- 5&lt;br /&gt;
fib &amp;lt;-- 3&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib &amp;lt;-- 2&lt;br /&gt;
fib &amp;lt;-- 0&lt;br /&gt;
fib --&amp;gt; 0&lt;br /&gt;
...&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib &amp;lt;-- 2&lt;br /&gt;
fib &amp;lt;-- 0&lt;br /&gt;
fib --&amp;gt; 0&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib --&amp;gt; 2&lt;br /&gt;
fib --&amp;gt; 3&lt;br /&gt;
fib --&amp;gt; 5&lt;br /&gt;
- : int = 5&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut remarquer que la fonction calcule plusieurs fois le même fib n.&lt;br /&gt;
Une optimisation consisterait à garder certaines valeurs en mémoire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On écrit fib2 de type &amp;quot;int -&amp;gt; int*int&amp;quot; qui renvoie le valeur de fib n (fst fib2 n) et fib n-1 (snd (fib2 n)) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib2 n = &lt;br /&gt;
if n&amp;lt;2 &lt;br /&gt;
   then (n,n-1)&lt;br /&gt;
   else let t = fib2 (n-1) in&lt;br /&gt;
      (fst(t)+snd(t),fst(t));;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 3&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comparer les fonctions fib et fib2, on les trace pour n=7 :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib 7 ;;&lt;br /&gt;
fib &amp;lt;-- 7&lt;br /&gt;
fib &amp;lt;-- 5&lt;br /&gt;
fib &amp;lt;-- 3&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
...&lt;br /&gt;
fib --&amp;gt; 3&lt;br /&gt;
fib --&amp;gt; 5&lt;br /&gt;
fib --&amp;gt; 8&lt;br /&gt;
fib --&amp;gt; 13&lt;br /&gt;
- : int = 13&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib2 7 ;;&lt;br /&gt;
fib2 &amp;lt;-- 7&lt;br /&gt;
fib2 &amp;lt;-- 6&lt;br /&gt;
fib2 &amp;lt;-- 5&lt;br /&gt;
fib2 &amp;lt;-- 4&lt;br /&gt;
fib2 &amp;lt;-- 3&lt;br /&gt;
fib2 &amp;lt;-- 2&lt;br /&gt;
fib2 &amp;lt;-- 1&lt;br /&gt;
fib2 --&amp;gt; (1, 0)&lt;br /&gt;
fib2 --&amp;gt; (1, 1)&lt;br /&gt;
fib2 --&amp;gt; (2, 1)&lt;br /&gt;
fib2 --&amp;gt; (3, 2)&lt;br /&gt;
fib2 --&amp;gt; (5, 3)&lt;br /&gt;
fib2 --&amp;gt; (8, 5)&lt;br /&gt;
fib2 --&amp;gt; (13, 8)&lt;br /&gt;
- : int * int = (13, 8)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On remarque que fib2 fait 14 calculs alors que fib en 81 pour n=7.&lt;br /&gt;
Afin de retourner uniquement la valeur de fib n on définit une nouvelle fonction, beaucoup plus rapide que fib, &lt;br /&gt;
en prenant le premier élément de la paire constituant fib2 n :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let fib n = fst ( fib2 n ) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 4 ( Bonus )&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On veut créer fib3 de type int-&amp;gt;int-&amp;gt;int-&amp;gt;int tel que :&lt;br /&gt;
&lt;br /&gt;
- son premier argument est l&#039;entier n pour fibonacci de n&lt;br /&gt;
&lt;br /&gt;
- les 2 autres arguments sont des accumulateurs qui permettent de conserver des valeurs successives ( pour i-1 et i )&lt;br /&gt;
&lt;br /&gt;
 --- à venir ---&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 2 : Manipulation des listes&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici quelque fonctions définies en utilisant &amp;lt;tt&amp;gt;List.fold_right&amp;lt;/tt&amp;gt; :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let longueur l = let f a r = 1 + r in List.fold_right f l 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let app f l = let f&#039; a r = ( f a )::r in List.fold_right f&#039; l []&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let concat l1 l2 = let f a r = a::r in List.fold_right l1 l2 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici la fonction reverse telle qu&#039;on l&#039;a écrite dans le TD&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec reverse l = &lt;br /&gt;
  match l with&lt;br /&gt;
  []-&amp;gt;[]&lt;br /&gt;
  |a::l -&amp;gt; (reverse l)@[a] ;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour la comparer avec la fonction &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; de Caml, on va regarder le temps d&#039;exécution sur une très grande liste.&lt;br /&gt;
&lt;br /&gt;
Pour cela, on créé une fonction qui fabrique une liste de n valeurs :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec longueliste  n = &lt;br /&gt;
  if n=0 &lt;br /&gt;
  then []&lt;br /&gt;
  else n::longueliste (n-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut tester les fonctions avec une liste de 10000 éléments.&lt;br /&gt;
&lt;br /&gt;
La fonction &amp;lt;tt&amp;gt;reverse&amp;lt;/tt&amp;gt; met environ 15s alors que &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; s&#039;exécute immédiatement.&lt;br /&gt;
&lt;br /&gt;
Cela montre donc que &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; est bien plus efficace que &amp;lt;tt&amp;gt;reverse&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::En fait, reverse fait ( n + n-1 + n-2 + ... + 1 ) opérations à chaque fois (il met le premier élément au bout de la liste et ainsi de suite) , soit au total &amp;lt;math&amp;gt;n*(n+1)/2 \sim n^2&amp;lt;/math&amp;gt; opérations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; utilise la fonction suivante :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec rev_append l1 l2 =&lt;br /&gt;
  match l1 with&lt;br /&gt;
    [] -&amp;gt; l2&lt;br /&gt;
  | a::l -&amp;gt; rev_append l (a::l2);;&lt;br /&gt;
&lt;br /&gt;
let rec rev l = rev_append l [];;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Elle fait donc environ &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; opérations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 3 : Deux algorithmes de tri pour les listes&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On programme une fonction d&#039;insertion qui permet d&#039;insérer un élément à sa place&lt;br /&gt;
dans une liste triée.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insertion n l =&lt;br /&gt;
  match l with&lt;br /&gt;
    [] -&amp;gt; [n]&lt;br /&gt;
  | a::l&#039; -&amp;gt; if n&amp;lt;=a&lt;br /&gt;
             then n::l&lt;br /&gt;
             else a::(insertion n l&#039;) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On programme ensuite le tri par insertion.&lt;br /&gt;
&lt;br /&gt;
Le tri par insertion fonctionne de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
- la liste vide est triée,&lt;br /&gt;
&lt;br /&gt;
- pour trier la liste &amp;quot;&amp;lt;tt&amp;gt;a::l&amp;lt;/tt&amp;gt;&amp;quot;, on commence par trier (récursivement) la liste &amp;lt;tt&amp;gt;l&amp;lt;/tt&amp;gt;, puis on insère&lt;br /&gt;
l&#039;élément &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; dans le résultat.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec tri_insertion l =&lt;br /&gt;
 match l with&lt;br /&gt;
    [] -&amp;gt; []&lt;br /&gt;
  | a::l&#039; -&amp;gt; insertion a (tri_insertion l&#039;) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ou plus simplement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let tri l = List.fold.right insertion l [] ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 3&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Maintenant, on programme une fonction fusionne qui permet de fusionner deux listes triées en une seule liste triée.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionne l1 l2 =&lt;br /&gt;
  match l1 with &lt;br /&gt;
     [] -&amp;gt; l2&lt;br /&gt;
   | a::l&#039; -&amp;gt; begin&lt;br /&gt;
                match l2 with&lt;br /&gt;
                   [] -&amp;gt; l1&lt;br /&gt;
                 | b::l&#039;&#039; -&amp;gt; if a&amp;lt;=b then ( a::fusionne l&#039; l2 ) &lt;br /&gt;
                                     else ( b::fusionne l1 l&#039;&#039;) &lt;br /&gt;
&lt;br /&gt;
              end;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour éviter d&#039;imbriquer des &amp;quot;match&amp;quot;, on peut aussi filtrer directement la paire &amp;lt;tt&amp;gt;(l1,l2)&amp;lt;/tt&amp;gt; et regrouper les cas d&#039;un des listes vides ensemble : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionnebis l1 l2 =&lt;br /&gt;
  match l1,l2 with&lt;br /&gt;
      [],l | l,[]  -&amp;gt;  l&lt;br /&gt;
    | (a::l&#039;, b::l2&#039;)  -&amp;gt; &lt;br /&gt;
        if a &amp;lt;= b&lt;br /&gt;
        then a::(fusionnebis l&#039; l2)&lt;br /&gt;
        else b::(fusionnebis l1 l2&#039;)  ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 4&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis une fonction sépare qui permet de séparer une liste quelconque en&lt;br /&gt;
deux listes de taille équivalente&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec separe l =&lt;br /&gt;
  match l with&lt;br /&gt;
     [] -&amp;gt; ([],[])&lt;br /&gt;
   | [a] -&amp;gt; ([a],[])&lt;br /&gt;
   | a::b::l&#039; -&amp;gt; let t=separe l&#039; in (a::(fst t),b::(snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 5&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On doit maintenant programmer un deuxième type de tri : le tri par fusion.&lt;br /&gt;
&lt;br /&gt;
Le tri fusion fonctionne de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
- la liste vide est triée,&lt;br /&gt;
&lt;br /&gt;
- pour trier une liste non-vide, on sépare la liste en deux parties de longueur égale (à un&lt;br /&gt;
élément prêt), on trie (récursivement) ces deux listes, puis on fusionne les deux résultats.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec tri_fusion l =  &lt;br /&gt;
  match l with&lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
   | [a] -&amp;gt; [a]&lt;br /&gt;
   | _ -&amp;gt; let t=separe l in&lt;br /&gt;
          fusionne (tri_fusion (fst t)) (tri_fusion (snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 6&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comparer l&#039;efficacité des deux fonctions de tri, on utilise la même méthode que précédemment : &lt;br /&gt;
&lt;br /&gt;
On créé a l&#039;aide d&#039;un fonction une liste aléatoire de 10000 éléments, les éléments étant non triés.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let liste_aleatoire n =&lt;br /&gt;
  let rec aux n max = &lt;br /&gt;
    if n=0&lt;br /&gt;
    then []&lt;br /&gt;
    else (Random.int max)::aux (n-1) max&lt;br /&gt;
  in&lt;br /&gt;
  aux n n ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite on trie cette liste avec les deux fonctions.&lt;br /&gt;
&lt;br /&gt;
Le tri_fusion renvoie instantanément une liste de 10000 éléments aléatoires triés. &lt;br /&gt;
&lt;br /&gt;
Le tri insertion, quant à lui, prend plus d&#039;une dizaine de secondes.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;Remarque :&#039;&#039; cela vient du fait que le tri fusion divise la taille de la liste par deux à chaque étape, alors que le tri par insertion soustrait un élément à chaque étape.&lt;br /&gt;
: On peut montrer que le temps de calcul pour le tri fusion est proportionnel à &amp;lt;math&amp;gt;n \log(n)&amp;lt;/math&amp;gt;, ce qui est très petit par rapport à &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt; (temps d&#039;execution moyen du tri par insertion) quand &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; est grand.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 7&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On souhaite trier une liste selon la hauteur des points c&#039;est-à-dire selon le deuxième élément de la paire de flottants.&lt;br /&gt;
Pour cela, il faudrait faire un tri fusion sur le 2eme élément de la paire représentant les points&lt;br /&gt;
tout en sauvegardant le 1er élément...&lt;br /&gt;
&lt;br /&gt;
On peut créer une fonction de tri par fusion générale, qui prend comme paramètre une autre fonction (qui sert à vérifier la comparaison de 2 éléments et rend true ou false) afin de choisir le tri que l&#039;on veut ( décroissant, croissant ... ) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionne comp l1 l2 =&lt;br /&gt;
 match (l1,l2) with&lt;br /&gt;
    ([],_) -&amp;gt; l2&lt;br /&gt;
  | (_,[]) -&amp;gt; l1&lt;br /&gt;
  | (a::l&#039;, b::l2&#039;) -&amp;gt; &lt;br /&gt;
     if (comp a b)&lt;br /&gt;
     then a::(fusionne l&#039; l2)&lt;br /&gt;
     else b::(fusionne l1 l2&#039;);;&lt;br /&gt;
&lt;br /&gt;
let rec tri_fusion comp l =  &lt;br /&gt;
 match l with&lt;br /&gt;
    [] -&amp;gt; []&lt;br /&gt;
  | [a] -&amp;gt; [a]&lt;br /&gt;
  | _ -&amp;gt; let t=separe l in&lt;br /&gt;
         fusionne comp (tri_fusion comp (fst t)) (tri_fusion comp (snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il suffit alors a l&#039;utilisateur de définir la fonction de comparaison pour ensuite faire appel à &amp;lt;tt&amp;gt;tri_fusion&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Par exemple, pour trier dans un ordre décroissant :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let dec a n  = if a&amp;gt;=n then true&lt;br /&gt;
else false ;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
ou même plus simplement&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let dec = (&amp;gt;=) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour trier une liste de paires, il faut créer une fonction qui compare les seconds membres ;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let paire a n  = (snd a) &amp;lt;= (snd n)  ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ici, les paires seront triées selon le second membre dans l&#039;ordre croissant.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 8 ( Bonus )&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un algorithme de tri est dit stable quand il ne modifie pas l&#039;ordre relatifs des éléments &amp;quot;égaux&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Par exemple, on tri par ordre croissant du premier membre une liste de paires de float : [ ( 5 , 3 ) ; ( -2 , 8 ) ; ( -2 , 2 ) ; ( 5 , 8 ) ; ( 5 , -8 ) ]  &lt;br /&gt;
&lt;br /&gt;
non stable : &amp;lt;tt&amp;gt;[(-2, 2); (-2, 8); (5, -8); (5, 8); (5, 3)]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
stable : &amp;lt;tt&amp;gt;[(-2, 8); (-2, 2); (5, 3); (5, 8); (5, -8)]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour qu&#039;un tri soit stable, la comparaison de deux éléments doit comprendre aussi le &amp;quot;=&amp;quot;, comme c&#039;est le cas pour les fonctions paire et dec.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD3== &amp;lt;br/&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Exercice 1 : les arbres binaires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt; Question 1 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type &#039;a arbre = Vide | Noeud of &#039;a*&#039;a arbre*&#039;a arbre ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 2 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
let rec taille a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; 1 + (taille g) + (taille d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction taille compte le nombre de noeuds que contient un arbre.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 3 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec applique f a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; Vide&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; Noeud(f e,applique f g,applique f d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction applique est équivalente à la fonction List.map&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 4 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec poids (f : &#039;a -&amp;gt; int) a = &lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; (f e) + (poids f g) + (poids f d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 5 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec reduit a o f =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; let x = reduit g o f in&lt;br /&gt;
       			let y = reduit d o f in&lt;br /&gt;
                        f e x y ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction reduit est equivalente à la fonction List.fold_right pour le type des arbres.&lt;br /&gt;
&lt;br /&gt;
Réécriture de taille et poids :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec taille a = reduit a 0 (fun e x y -&amp;gt; 1 + x + y) ;;&lt;br /&gt;
let rec poids f a = reduit a 0 (fun e x y -&amp;gt; (f e) + (f x) + (f y)) ;; (*?????*)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 6 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec collecte a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; []&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; e::(collecte g)@(collecte d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction collecte récupère tous les éléments de l&#039;arbre et les renvoie sous forme d&#039;une liste.&lt;br /&gt;
&lt;br /&gt;
Avec la fonction reduit :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec collecte a = reduit a [] (fun e x y -&amp;gt; e::x@y) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 7 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec feuilles a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; []&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; if (g=Vide &amp;amp;&amp;amp; d=Vide) then [e]&lt;br /&gt;
       			else (feuilles g)@(feuilles d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Avec reduit :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec feuilles a = reduit a [] (fun e x y -&amp;gt; if (x=[] &amp;amp;&amp;amp; y=[]) then [e]&lt;br /&gt;
					       else x@y) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Exercice 2 : la tortue &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt; Question 1 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type action = Forward of int | Left of int | SetPos of int*int | SetHeading of int | PenUp | Pendown ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 2 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
let rec ecrit (l:action list) (pen:bool) : bool =&lt;br /&gt;
   match l with&lt;br /&gt;
    	[] -&amp;gt; false&lt;br /&gt;
       |(Forward d)::l -&amp;gt; if (d=0 || pen=false) then ecrit l pen&lt;br /&gt;
                          else true &lt;br /&gt;
       |PenUp::l -&amp;gt; ecrit l false&lt;br /&gt;
       |PenDown::l -&amp;gt; ecrit l true&lt;br /&gt;
       | _ -&amp;gt; ecrit l pen ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction ecrit renvoie true si la tortue écrit qqch ou false sinon.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 3 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec pos (x:int) (y:int) (a:int) (l:action list) : ((int*int)int) =&lt;br /&gt;
   match l with&lt;br /&gt;
    	[] -&amp;gt; ((x,y),a)&lt;br /&gt;
       |PenUp::l |Pendown::l -&amp;gt; pos x y a l&lt;br /&gt;
       |(Left b)::l -&amp;gt; pos x y (a+b) l&lt;br /&gt;
       |(SetPos(x&#039;,y&#039;))::l -&amp;gt; pos x&#039; y&#039; a l&lt;br /&gt;
       |(SetHeading b)::l -&amp;gt; pos x y b l &lt;br /&gt;
       |(Forward d)::l -&amp;gt; pos (x+(sin a)*d) (y+(cos a)*d) a l ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 5 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type action = Forward of int | SetPos of int*int | SetHeading of int | Left of int | PenUp | Pendown | Repeat of int*action list ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD4==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 1 : Petits exercices combinatoires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On commence par créer une fonction intermédiaire.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supp&#039; x l =&lt;br /&gt;
   match l with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |b::f&#039;-&amp;gt; if (x=b) then supp&#039; x l&#039;&lt;br /&gt;
                        else b::supp&#039; x f&#039;;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supp l =&lt;br /&gt;
   match l with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |a::l&#039;-&amp;gt; a::supp supp&#039; a l&#039;;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 2 : Dictionnaires &amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Un dictionnaire est une liste de paires&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Question 2 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insere c v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[(c,v)]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (c=c&#039;) then (c&#039;,v&#039;)::(insere c v d)&lt;br /&gt;
                               else (c,v)::d ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supprime c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (c=c&#039;) then d&lt;br /&gt;
                               else (c&#039;,v&#039;)::(supprime c d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec existe_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; false&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; (c=c&#039;) || existe_cle c d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec existe_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; false&lt;br /&gt;
      |(_,v&#039;)::d -&amp;gt; if (v=v&#039;) then true&lt;br /&gt;
                              else existe_val v d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec recherche_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; None&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; if (c=c&#039;) then Some c&#039;&lt;br /&gt;
                              else recherche_cle c d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* liste des valeurs de c par on peut avoir plusieurs cases, et donc plusieurs clés, avec une même valeur *)&lt;br /&gt;
let rec recherche_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (v=v&#039;) then c&#039;::(recherche_val v d)&lt;br /&gt;
                              else recherche_val v d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Liste des clés *)&lt;br /&gt;
let rec liste_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; []&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; c&#039;::(liste_cle c d);;&lt;br /&gt;
&lt;br /&gt;
(* Liste des valeurs *)&lt;br /&gt;
let rec liste_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(_,v&#039;)::d -&amp;gt; v&#039;::(liste_val v d);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut également utiliser des fonctions existantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Liste des clés *)&lt;br /&gt;
let liste_cle d = List.map fst;;&lt;br /&gt;
&lt;br /&gt;
(* Liste des valeurs, attention aux doublons! *)&lt;br /&gt;
let liste_val d = suppr_doublons(List.map snd);;&lt;br /&gt;
  &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 4 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec zip l1 l2&lt;br /&gt;
   match l1 l2 with&lt;br /&gt;
      [].[]-&amp;gt;[]&lt;br /&gt;
      |c::lc, v::lv -&amp;gt; (c,v)::(zip lc lv)&lt;br /&gt;
      |_,_ -&amp;gt; [];;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 5 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On aurait pu utiliser une liste triée : si par exemple on cherche 12 et qu&#039;on en est à 14 dans la liste, on sait que 12 n&#039;y est pas. PB : ceci n&#039;empêche pas d&#039;aller à la fin de la liste si la valeur ou la clé recherchée est grande ... &amp;lt;br/&amp;gt;&lt;br /&gt;
Une recherche dichotomique est inefficace sur les listes ... &amp;lt;br/&amp;gt;&lt;br /&gt;
   =&amp;gt; dans la bibliothèque hash table de Caml, il existe un List.zip&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 3 : Arbres binaires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Question 1 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
La profondeur d&#039;un arbre binaire correspond au nombre d&#039;étage : on regarde à partir de la première racine et des sous arbres, on calcule la profondeur à gauche et la profondeur à droite, on prend la plus grande et on y ajoute 1. &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec profondeur a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; 0&lt;br /&gt;
      |Noeud(_,g,d) -&amp;gt; 1 + max(profondeurg) (profondeurd);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 2 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec equilibre a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; true&lt;br /&gt;
      |Noeud(_,g,d) -&amp;gt; if (profondeur g)=(profondeur d) || (profondeur g)=(profondeur d +1) || (profondeur g +1)=(profondeur d)&lt;br /&gt;
                          then (equilibre d)&amp;amp;&amp;amp;(equilibre g)&lt;br /&gt;
                          else false;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec present e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; false&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; e&#039;=e || present e g || present e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 4 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec present e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; false&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; if (e&#039;=e) then true&lt;br /&gt;
                                  else  if (e&amp;lt;e&#039;) then present e g&lt;br /&gt;
                                                  else present e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 5 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insere e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; e&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; if (e&amp;lt;e&#039;) then insere e g&lt;br /&gt;
                                  else insere e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Laurent corantin</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=INFO401_corr_TD_TP&amp;diff=4143</id>
		<title>INFO401 corr TD TP</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=INFO401_corr_TD_TP&amp;diff=4143"/>
		<updated>2009-04-28T12:59:36Z</updated>

		<summary type="html">&lt;p&gt;Laurent corantin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Préliminaires==&lt;br /&gt;
&lt;br /&gt;
Pour afficher correctement dans le wiki, allez voir un peu comment on fait. Vous pouvez regarder par exemple sur le [[INFO401 | wiki du cours]] ou directement sur des articles de [http://fr.wikipedia.org/wiki/Accueil Wikipedia]. La documentation de mediawiki se trouve [http://meta.wikimedia.org/wiki/Aide:Éditeur ici].&lt;br /&gt;
&lt;br /&gt;
Un truc important : pour rentrer du code Caml, il faut mettre les balises &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;...&amp;lt;/source&amp;gt;&amp;lt;/nowiki&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; autour de votre code. Allez par exemple voir le début de la section sur [[#Le TD1 et le TP0 | le TD1 et TP0]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Vous pouvez aller discuter des corrections dans les sujets de discussions associes...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD1 et le TP0==&lt;br /&gt;
&lt;br /&gt;
Pour vous montrer un exemple de ce que j&#039;attends, voila la correction de la fonction factorielle. (C&#039;était facile...) J&#039;ai volontairement mis beaucoup de commentaires...&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;La fonction factorielle (TD1, exercice 2, question 2)&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le but est de calculer la fonction &amp;lt;math&amp;gt;!n = 1\times2\times \cdots \times n&amp;lt;/math&amp;gt; par récurrence. La version typée est verbeuse de la fonction correspondante en Caml donne :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* fonction factorielle : c&#039;est la factorielle habituelle des mathématiciens... *)&lt;br /&gt;
let rec fact (n:int) : int =&lt;br /&gt;
  if (n&amp;gt;1)&lt;br /&gt;
  then  n * (fact (n-1))&lt;br /&gt;
  else 1      (* rq : pour que le programme ne boucle pas sur les valeurs négatives, on renvoie 1 dés que n&amp;lt;1 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Comme la fonction est récursive, il ne faut pas oublier le &amp;lt;tt&amp;gt;rec&amp;lt;/tt&amp;gt; au début de la définition.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On aurait pu faire une autre version, qui fonctionne différemment sur les nombres négatifs :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fact&#039; = function&lt;br /&gt;
   n when (n&amp;gt;0) -&amp;gt; n * fact&#039; (n-1)&lt;br /&gt;
 | n when (n&amp;lt;0) -&amp;gt; n * fact&#039; (n+1)&lt;br /&gt;
 | _ -&amp;gt; 1  (* si n n&#039;est ni plus petit que 0 ni plus grand que 0, n est égal à 0, et on renvoie donc 1 *)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
J&#039;ai volontairement mis une version qui contient plusieurs choses que nous n&#039;avons pas encore vues en cours :&lt;br /&gt;
* utilisation de &amp;quot;&amp;lt;tt&amp;gt;function&amp;lt;/tt&amp;gt;&amp;quot; plutôt que &amp;lt;tt&amp;gt;fun&amp;lt;/tt&amp;gt;,&lt;br /&gt;
* le symbole &amp;quot;&amp;lt;tt&amp;gt;|&amp;lt;/tt&amp;gt;&amp;quot;,&lt;br /&gt;
* le mot clé &amp;quot;&amp;lt;tt&amp;gt;when&amp;lt;/tt&amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Vous devriez pouvoir comprendre ce que fait la fonction. Sinon, voici une version que vous auriez pu écrire :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fact_bis = fun n -&amp;gt;&lt;br /&gt;
  if (n=0)&lt;br /&gt;
  then 1&lt;br /&gt;
  else begin&lt;br /&gt;
    if (n&amp;gt;0)&lt;br /&gt;
    then n*fact_bis (n-1)&lt;br /&gt;
    else n*fact_bis (n+1)   (* dans ce cas, n est forcement négatif *)&lt;br /&gt;
  end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Les fonctions sommes &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il s&#039;agit ici d&#039;écrire la fonction qui va additionner les carrés des entiers de 1 jusqu&#039;à un nombre donné.&lt;br /&gt;
&lt;br /&gt;
Cela donne :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_carre b =&lt;br /&gt;
if (b=0) then 0&lt;br /&gt;
else (b*b) + somme_carre (b-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite on nous demande de calculer la somme des cubes des entiers de 1 jusqu&#039;à un nombre donné. On pourrait faire le même programme en remplaçant b*b par b*b*b, mais on va définir une fonction puissance (car elle n&#039;existe pas d&#039;origine sous Caml), qui nous servira aussi pour la suite... :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec puissance x a =&lt;br /&gt;
if (a = 0) then 1&lt;br /&gt;
else x * puissance x (a-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On doit maintenant calculer la somme des &amp;lt;math&amp;gt;i^i&amp;lt;/math&amp;gt;, i variant de 1 à un nombre donné :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_puissance b =&lt;br /&gt;
if (b=0) then 0&lt;br /&gt;
else (puissance b b) + somme_puissance (b-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut définir une unique fonction qui permettrait de faire toutes ces sommes, celle-ci aura pour argument une fonction quelconque :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec somme_fonction n f = (* f étant une fonction *)&lt;br /&gt;
if (n=0) then f 0&lt;br /&gt;
else f n + somme_fonction (n-1) f;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
cette fonction est de type &amp;quot;&amp;lt;tt&amp;gt;int -&amp;gt; fun -&amp;gt; int&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Nombres pairs et impairs (TP0 Partie 2 Question 2) &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il faut écrire les fonctions récursives pairs et impairs, qui renvoient vrai si le nombre est pair (respectivement impair) et faux si le nombre est impair (respectivement pair);&lt;br /&gt;
Ici nous devons déclarer simultanément les deux fonctions, car chacune fait appel à l&#039;autre lors de son exécution.&lt;br /&gt;
&lt;br /&gt;
Cela donne :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec pair n =&lt;br /&gt;
  if (n=0) then true&lt;br /&gt;
  else impair (n-1)&lt;br /&gt;
and impair n =&lt;br /&gt;
  if (n=0) then false&lt;br /&gt;
  else  pair (n-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Suite de Fibonacci &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La suite de fibonacci est tel que u&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt;=0 u&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;=1 et u&amp;lt;sub&amp;gt;n+2&amp;lt;/sub&amp;gt;=u&amp;lt;sub&amp;gt;n+1&amp;lt;/sub&amp;gt;+u&amp;lt;sub&amp;gt;n&amp;lt;/sub&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib n =&lt;br /&gt;
if (n=0) then 0&lt;br /&gt;
else if (n=1) then 1&lt;br /&gt;
else fib (n-1) + fib (n-2);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La plus grande valeur que l&#039;on peut obtenir sans que cela soit trop long est 24157817, ce qui correspond à fib 37.&lt;br /&gt;
Nous trouvons qu&#039;il faut déjà 88 additions pour calculer fib 10.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Rq :&#039;&#039;&#039; fib de 37 prend effectivement beaucoup de temps. Il faut 39088168 additions avant d&#039;en arriver à bout. Il est possible de faire une version de Fibonacci qui va très vite et qui calcule &amp;lt;tt&amp;gt;fib 37&amp;lt;/tt&amp;gt; en seulement 36 additions...&lt;br /&gt;
: Comment ?&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Dragon ! &amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;i&amp;gt; Le dragon est une créature mythique, présente dans de nombreuses cultures.&lt;br /&gt;
  On peut déterminer deux grands types de dragons : le dragon occidental et le dragon oriental&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction dragon a pour but de dessiner un dragon, pour cela on utilise une fonction récursive qui admet pour argument le nombre n d&#039;itération de la fonction, et les coordonnées de 2 points. A chaque itération, la fonction calcule pour chaque segment, un nouveau point et le relie ensuite aux deux autres.&lt;br /&gt;
&lt;br /&gt;
On obtient en tout 2&amp;lt;sup&amp;gt;n&amp;lt;/sup&amp;gt; segments entremêlés, qui forment un dragon.&lt;br /&gt;
&lt;br /&gt;
Let&#039;s go !&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec dragon (n:int) (a:int) (b:int) (c:int) (d:int) : unit =&lt;br /&gt;
if (n = 0) then (moveto a b ; lineto c d)&lt;br /&gt;
               else begin&lt;br /&gt;
                      let x = (a+c+d-b)/2 in&lt;br /&gt;
                      let y = (b+d+a-c)/2 in&lt;br /&gt;
                      dragon (n-1) a b x y ;&lt;br /&gt;
                      dragon (n-1) c d x y&lt;br /&gt;
                    end ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;&#039;Rq : &#039;&#039;&#039; votre version du dragon est bien, mais pas très précises. (Je chipote un peu...)  Pour les paramètres (&amp;lt;tt&amp;gt;dragon 11 100 100 400 400&amp;lt;/tt&amp;gt;), de nombreux carrés ne sont pas bien tracés.&lt;br /&gt;
:Comment expliquez-vous cela, et comment pouvez-vous le corriger ?&lt;br /&gt;
&lt;br /&gt;
::Pour améliorer la précision je suggère de passer les coordonnées en type Float. --[[Utilisateur:Nicolas|Nicolas]] 31 janvier 2009 à 11:42 (CET)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD2==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exercice 1 : Tuples&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 4 :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
On définit la fonction curry par:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let curry (f: &#039;a * &#039;b -&amp;gt; &#039;c) : &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;c&lt;br /&gt;
     = fun x y -&amp;gt; f(x,y);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ou encore en simplifiant:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let curry f x y = f(x,y);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
On définit ensuite la fonction uncurry par:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry (f: &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;c) : &#039;a * &#039;b -&amp;gt; &#039;c&lt;br /&gt;
     = fun x -&amp;gt; f (fst x) (snd x);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ou encore de trois autres manières plus simplifiées:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = fun x -&amp;gt; f (fst x) (snd x);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = fun x -&amp;gt; match x with (a,b) -&amp;gt; f a b;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let uncurry f = function (a,b) -&amp;gt; f a b;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Avantage de la première forme (à plusieurs arguments): Elle permet une application partielle: on peut appliquer cette fonction à une seule partie des arguments.&lt;br /&gt;
&lt;br /&gt;
Inconvénients de la seconde forme (à un argument): &lt;br /&gt;
*il faut faire appel à fst, snd;&lt;br /&gt;
*Caml doit séparer les paires: c&#039;est une perte de temps&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 5 :&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
D&#039;après la fonction récursive Fibonacci définit par &amp;lt;br /&amp;gt;&lt;br /&gt;
f(0)=0 &amp;lt;br /&amp;gt;&lt;br /&gt;
f(1)=1 &amp;lt;br /&amp;gt;&lt;br /&gt;
f(n+2)=f(n+1)+f(n), &amp;lt;br /&amp;gt;&lt;br /&gt;
comment compter le nombre d&#039;appels récursifs en Caml? &amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* la fonction renvoie une valeur de type int*int :&lt;br /&gt;
  - la première composante est la valeur de Fibonacci pour n,&lt;br /&gt;
  - la seconde composante est le nonbre d&#039;appels recursifs effectués *)&lt;br /&gt;
 let rec fib n =&lt;br /&gt;
     if (n&amp;lt;2) then (n,0)&lt;br /&gt;
     else let t = fib (n-1) in&lt;br /&gt;
          let s = fib (n-2) in &lt;br /&gt;
     (fst t + fst s , snd t + snd s + 1)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&#039;&#039;exemple : &#039;&#039;fib 10 = (55, 88) pour exécuter la fonction Fibonacci(10), il y a 88 appels récursifs nécessaires...&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Exercice 2 : Listes&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 5 :&#039;&#039;&#039;&amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;&lt;br /&gt;
suite à l&#039;étude des fonctions &lt;br /&gt;
*longueur&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec longueur l =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; 0&lt;br /&gt;
     | _::l -&amp;gt; 1 + longueur l&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*applique&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec app f p =&lt;br /&gt;
     match p with &lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
     | a :: p -&amp;gt; f(a) :: app f p&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*concatene&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec cat l1 l2 =&lt;br /&gt;
     match l1 with&lt;br /&gt;
     [] -&amp;gt; l2&lt;br /&gt;
     | a :: l -&amp;gt; a :: (cat l l2)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
*renverse,&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec renverse l =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
     | a :: l -&amp;gt; (renverse l) @ [a]&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
on remarque des similitudes. Ces fonctions ont le même schéma de base. On peut résumer le principe commun dans la fonction suivante :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
 let rec reduit l o f =&lt;br /&gt;
     match l with&lt;br /&gt;
     [] -&amp;gt; o&lt;br /&gt;
     | a :: l -&amp;gt; let appel_rec = reduit l o f in&lt;br /&gt;
                 f a appel_rec&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&#039;&#039;NB :&#039;&#039; le type de &amp;lt;tt&amp;gt;reduit&amp;lt;/tt&amp;gt; donné par Caml est : &amp;lt;tt&amp;gt;val reduit : &#039;a list -&amp;gt; &#039;b -&amp;gt; (&#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b) -&amp;gt; &#039;b = &amp;lt;fun&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Question 6 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
Reprogrammons les fonctions précédentes à partir de la fonction reduit ! &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let longueur l =&lt;br /&gt;
     let f _ r = 1 + r in &lt;br /&gt;
     reduit l 0 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let app g l =&lt;br /&gt;
     let f a r = (g a)::r in&lt;br /&gt;
     reduit l [] f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let cat l1 l2 =&lt;br /&gt;
     let f a r = a :: r in  &lt;br /&gt;
     reduit l1 l2 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut également introduire la fonction directement avec un &amp;lt;tt&amp;gt;fun&amp;lt;/tt&amp;gt; de la maniere suivante : &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let renverse l = reduit l [] (fun a r -&amp;gt; r @ [a])&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 7 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Le type de la fonction reduit est: ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b ) -&amp;gt; &#039;a list &amp;lt;br/&amp;gt;&lt;br /&gt;
Celui de la fonction List.fold_right est: ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;b ) -&amp;gt; &#039;a list -&amp;gt; &#039;b -&amp;gt; &#039;b  ;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
l&#039;ordre des arguments de fold_right est le même que l&#039;ordre des arguments de reduit. La fonction fold_right compte juste deux arguments supplémentaires.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Question 8 :&#039;&#039;&#039;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici la fonction fold_left:&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
 let rec fold_left f b l=&lt;br /&gt;
      match l with&lt;br /&gt;
        []-&amp;gt;b&lt;br /&gt;
       |a::l -&amp;gt; fold_left f (f b a) l;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Cette fonction est &#039;&#039;récursive terminale&#039;&#039;, de type ( &#039;a -&amp;gt; &#039;b -&amp;gt; &#039;a ) -&amp;gt; &#039;a -&amp;gt; &#039;b list -&amp;gt; &#039;a .&lt;br /&gt;
&lt;br /&gt;
==Le TP1 - début==&lt;br /&gt;
&lt;br /&gt;
Le sujet [http://www.lama.univ-savoie.fr/~hyvernat/Enseignement/0809/info401/tp1.pdf programmes récursifs, listes], au format pdf.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 1 : Quelques compléments sur les programmes récursifs&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dans cette partie, on travaille sur la fonction Fibonacci&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On commence par l&#039;utiliser sous la forme :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib n =&lt;br /&gt;
if n&amp;lt;2&lt;br /&gt;
   then n&lt;br /&gt;
   else fib (n-1) + fib (n-2)&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comprendre ce qu&#039;il se passe, on trace la fonction à l&#039;aide de &amp;quot;#trace&amp;quot; pour fib 5&lt;br /&gt;
&lt;br /&gt;
fib &amp;lt;-- n veut dire que l&#039;on donne la valeur n à la fonction fib&lt;br /&gt;
&lt;br /&gt;
alors que fib --&amp;gt; n veut dire que fib renvoie n&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib 5 ;;&lt;br /&gt;
fib &amp;lt;-- 5&lt;br /&gt;
fib &amp;lt;-- 3&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib &amp;lt;-- 2&lt;br /&gt;
fib &amp;lt;-- 0&lt;br /&gt;
fib --&amp;gt; 0&lt;br /&gt;
...&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib &amp;lt;-- 2&lt;br /&gt;
fib &amp;lt;-- 0&lt;br /&gt;
fib --&amp;gt; 0&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib --&amp;gt; 1&lt;br /&gt;
fib --&amp;gt; 2&lt;br /&gt;
fib --&amp;gt; 3&lt;br /&gt;
fib --&amp;gt; 5&lt;br /&gt;
- : int = 5&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut remarquer que la fonction calcule plusieurs fois le même fib n.&lt;br /&gt;
Une optimisation consisterait à garder certaines valeurs en mémoire.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On écrit fib2 de type &amp;quot;int -&amp;gt; int*int&amp;quot; qui renvoie le valeur de fib n (fst fib2 n) et fib n-1 (snd (fib2 n)) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fib2 n = &lt;br /&gt;
if n&amp;lt;2 &lt;br /&gt;
   then (n,n-1)&lt;br /&gt;
   else let t = fib2 (n-1) in&lt;br /&gt;
      (fst(t)+snd(t),fst(t));;&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 3&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comparer les fonctions fib et fib2, on les trace pour n=7 :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib 7 ;;&lt;br /&gt;
fib &amp;lt;-- 7&lt;br /&gt;
fib &amp;lt;-- 5&lt;br /&gt;
fib &amp;lt;-- 3&lt;br /&gt;
fib &amp;lt;-- 1&lt;br /&gt;
...&lt;br /&gt;
fib --&amp;gt; 3&lt;br /&gt;
fib --&amp;gt; 5&lt;br /&gt;
fib --&amp;gt; 8&lt;br /&gt;
fib --&amp;gt; 13&lt;br /&gt;
- : int = 13&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
# fib2 7 ;;&lt;br /&gt;
fib2 &amp;lt;-- 7&lt;br /&gt;
fib2 &amp;lt;-- 6&lt;br /&gt;
fib2 &amp;lt;-- 5&lt;br /&gt;
fib2 &amp;lt;-- 4&lt;br /&gt;
fib2 &amp;lt;-- 3&lt;br /&gt;
fib2 &amp;lt;-- 2&lt;br /&gt;
fib2 &amp;lt;-- 1&lt;br /&gt;
fib2 --&amp;gt; (1, 0)&lt;br /&gt;
fib2 --&amp;gt; (1, 1)&lt;br /&gt;
fib2 --&amp;gt; (2, 1)&lt;br /&gt;
fib2 --&amp;gt; (3, 2)&lt;br /&gt;
fib2 --&amp;gt; (5, 3)&lt;br /&gt;
fib2 --&amp;gt; (8, 5)&lt;br /&gt;
fib2 --&amp;gt; (13, 8)&lt;br /&gt;
- : int * int = (13, 8)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
On remarque que fib2 fait 14 calculs alors que fib en 81 pour n=7.&lt;br /&gt;
Afin de retourner uniquement la valeur de fib n on définit une nouvelle fonction, beaucoup plus rapide que fib, &lt;br /&gt;
en prenant le premier élément de la paire constituant fib2 n :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let fib n = fst ( fib2 n ) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 4 ( Bonus )&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On veut créer fib3 de type int-&amp;gt;int-&amp;gt;int-&amp;gt;int tel que :&lt;br /&gt;
&lt;br /&gt;
- son premier argument est l&#039;entier n pour fibonacci de n&lt;br /&gt;
&lt;br /&gt;
- les 2 autres arguments sont des accumulateurs qui permettent de conserver des valeurs successives ( pour i-1 et i )&lt;br /&gt;
&lt;br /&gt;
 --- à venir ---&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 2 : Manipulation des listes&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici quelque fonctions définies en utilisant &amp;lt;tt&amp;gt;List.fold_right&amp;lt;/tt&amp;gt; :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let longueur l = let f a r = 1 + r in List.fold_right f l 0&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let app f l = let f&#039; a r = ( f a )::r in List.fold_right f&#039; l []&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let concat l1 l2 = let f a r = a::r in List.fold_right l1 l2 f&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Voici la fonction reverse telle qu&#039;on l&#039;a écrite dans le TD&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec reverse l = &lt;br /&gt;
  match l with&lt;br /&gt;
  []-&amp;gt;[]&lt;br /&gt;
  |a::l -&amp;gt; (reverse l)@[a] ;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour la comparer avec la fonction &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; de Caml, on va regarder le temps d&#039;exécution sur une très grande liste.&lt;br /&gt;
&lt;br /&gt;
Pour cela, on créé une fonction qui fabrique une liste de n valeurs :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec longueliste  n = &lt;br /&gt;
  if n=0 &lt;br /&gt;
  then []&lt;br /&gt;
  else n::longueliste (n-1);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut tester les fonctions avec une liste de 10000 éléments.&lt;br /&gt;
&lt;br /&gt;
La fonction &amp;lt;tt&amp;gt;reverse&amp;lt;/tt&amp;gt; met environ 15s alors que &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; s&#039;exécute immédiatement.&lt;br /&gt;
&lt;br /&gt;
Cela montre donc que &amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; est bien plus efficace que &amp;lt;tt&amp;gt;reverse&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
::En fait, reverse fait ( n + n-1 + n-2 + ... + 1 ) opérations à chaque fois (il met le premier élément au bout de la liste et ainsi de suite) , soit au total &amp;lt;math&amp;gt;n*(n+1)/2 \sim n^2&amp;lt;/math&amp;gt; opérations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;List.rev&amp;lt;/tt&amp;gt; utilise la fonction suivante :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec rev_append l1 l2 =&lt;br /&gt;
  match l1 with&lt;br /&gt;
    [] -&amp;gt; l2&lt;br /&gt;
  | a::l -&amp;gt; rev_append l (a::l2);;&lt;br /&gt;
&lt;br /&gt;
let rec rev l = rev_append l [];;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Elle fait donc environ &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; opérations.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;&#039;&#039;&#039;Partie 3 : Deux algorithmes de tri pour les listes&#039;&#039;&#039;&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 1&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On programme une fonction d&#039;insertion qui permet d&#039;insérer un élément à sa place&lt;br /&gt;
dans une liste triée.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insertion n l =&lt;br /&gt;
  match l with&lt;br /&gt;
    [] -&amp;gt; [n]&lt;br /&gt;
  | a::l&#039; -&amp;gt; if n&amp;lt;=a&lt;br /&gt;
             then n::l&lt;br /&gt;
             else a::(insertion n l&#039;) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 2&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On programme ensuite le tri par insertion.&lt;br /&gt;
&lt;br /&gt;
Le tri par insertion fonctionne de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
- la liste vide est triée,&lt;br /&gt;
&lt;br /&gt;
- pour trier la liste &amp;quot;&amp;lt;tt&amp;gt;a::l&amp;lt;/tt&amp;gt;&amp;quot;, on commence par trier (récursivement) la liste &amp;lt;tt&amp;gt;l&amp;lt;/tt&amp;gt;, puis on insère&lt;br /&gt;
l&#039;élément &amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt; dans le résultat.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec tri_insertion l =&lt;br /&gt;
 match l with&lt;br /&gt;
    [] -&amp;gt; []&lt;br /&gt;
  | a::l&#039; -&amp;gt; insertion a (tri_insertion l&#039;) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ou plus simplement :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let tri l = List.fold.right insertion l [] ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 3&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Maintenant, on programme une fonction fusionne qui permet de fusionner deux listes triées en une seule liste triée.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionne l1 l2 =&lt;br /&gt;
  match l1 with &lt;br /&gt;
     [] -&amp;gt; l2&lt;br /&gt;
   | a::l&#039; -&amp;gt; begin&lt;br /&gt;
                match l2 with&lt;br /&gt;
                   [] -&amp;gt; l1&lt;br /&gt;
                 | b::l&#039;&#039; -&amp;gt; if a&amp;lt;=b then ( a::fusionne l&#039; l2 ) &lt;br /&gt;
                                     else ( b::fusionne l1 l&#039;&#039;) &lt;br /&gt;
&lt;br /&gt;
              end;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour éviter d&#039;imbriquer des &amp;quot;match&amp;quot;, on peut aussi filtrer directement la paire &amp;lt;tt&amp;gt;(l1,l2)&amp;lt;/tt&amp;gt; et regrouper les cas d&#039;un des listes vides ensemble : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionnebis l1 l2 =&lt;br /&gt;
  match l1,l2 with&lt;br /&gt;
      [],l | l,[]  -&amp;gt;  l&lt;br /&gt;
    | (a::l&#039;, b::l2&#039;)  -&amp;gt; &lt;br /&gt;
        if a &amp;lt;= b&lt;br /&gt;
        then a::(fusionnebis l&#039; l2)&lt;br /&gt;
        else b::(fusionnebis l1 l2&#039;)  ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 4&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Puis une fonction sépare qui permet de séparer une liste quelconque en&lt;br /&gt;
deux listes de taille équivalente&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec separe l =&lt;br /&gt;
  match l with&lt;br /&gt;
     [] -&amp;gt; ([],[])&lt;br /&gt;
   | [a] -&amp;gt; ([a],[])&lt;br /&gt;
   | a::b::l&#039; -&amp;gt; let t=separe l&#039; in (a::(fst t),b::(snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 5&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On doit maintenant programmer un deuxième type de tri : le tri par fusion.&lt;br /&gt;
&lt;br /&gt;
Le tri fusion fonctionne de la manière suivante :&lt;br /&gt;
&lt;br /&gt;
- la liste vide est triée,&lt;br /&gt;
&lt;br /&gt;
- pour trier une liste non-vide, on sépare la liste en deux parties de longueur égale (à un&lt;br /&gt;
élément prêt), on trie (récursivement) ces deux listes, puis on fusionne les deux résultats.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec tri_fusion l =  &lt;br /&gt;
  match l with&lt;br /&gt;
     [] -&amp;gt; []&lt;br /&gt;
   | [a] -&amp;gt; [a]&lt;br /&gt;
   | _ -&amp;gt; let t=separe l in&lt;br /&gt;
          fusionne (tri_fusion (fst t)) (tri_fusion (snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 6&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Pour comparer l&#039;efficacité des deux fonctions de tri, on utilise la même méthode que précédemment : &lt;br /&gt;
&lt;br /&gt;
On créé a l&#039;aide d&#039;un fonction une liste aléatoire de 10000 éléments, les éléments étant non triés.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let liste_aleatoire n =&lt;br /&gt;
  let rec aux n max = &lt;br /&gt;
    if n=0&lt;br /&gt;
    then []&lt;br /&gt;
    else (Random.int max)::aux (n-1) max&lt;br /&gt;
  in&lt;br /&gt;
  aux n n ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ensuite on trie cette liste avec les deux fonctions.&lt;br /&gt;
&lt;br /&gt;
Le tri_fusion renvoie instantanément une liste de 10000 éléments aléatoires triés. &lt;br /&gt;
&lt;br /&gt;
Le tri insertion, quant à lui, prend plus d&#039;une dizaine de secondes.&lt;br /&gt;
&lt;br /&gt;
:&#039;&#039;Remarque :&#039;&#039; cela vient du fait que le tri fusion divise la taille de la liste par deux à chaque étape, alors que le tri par insertion soustrait un élément à chaque étape.&lt;br /&gt;
: On peut montrer que le temps de calcul pour le tri fusion est proportionnel à &amp;lt;math&amp;gt;n \log(n)&amp;lt;/math&amp;gt;, ce qui est très petit par rapport à &amp;lt;math&amp;gt;n^2&amp;lt;/math&amp;gt; (temps d&#039;execution moyen du tri par insertion) quand &amp;lt;math&amp;gt;n&amp;lt;/math&amp;gt; est grand.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 7&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On souhaite trier une liste selon la hauteur des points c&#039;est-à-dire selon le deuxième élément de la paire de flottants.&lt;br /&gt;
Pour cela, il faudrait faire un tri fusion sur le 2eme élément de la paire représentant les points&lt;br /&gt;
tout en sauvegardant le 1er élément...&lt;br /&gt;
&lt;br /&gt;
On peut créer une fonction de tri par fusion générale, qui prend comme paramètre une autre fonction (qui sert à vérifier la comparaison de 2 éléments et rend true ou false) afin de choisir le tri que l&#039;on veut ( décroissant, croissant ... ) :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec fusionne comp l1 l2 =&lt;br /&gt;
 match (l1,l2) with&lt;br /&gt;
    ([],_) -&amp;gt; l2&lt;br /&gt;
  | (_,[]) -&amp;gt; l1&lt;br /&gt;
  | (a::l&#039;, b::l2&#039;) -&amp;gt; &lt;br /&gt;
     if (comp a b)&lt;br /&gt;
     then a::(fusionne l&#039; l2)&lt;br /&gt;
     else b::(fusionne l1 l2&#039;);;&lt;br /&gt;
&lt;br /&gt;
let rec tri_fusion comp l =  &lt;br /&gt;
 match l with&lt;br /&gt;
    [] -&amp;gt; []&lt;br /&gt;
  | [a] -&amp;gt; [a]&lt;br /&gt;
  | _ -&amp;gt; let t=separe l in&lt;br /&gt;
         fusionne comp (tri_fusion comp (fst t)) (tri_fusion comp (snd t)) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Il suffit alors a l&#039;utilisateur de définir la fonction de comparaison pour ensuite faire appel à &amp;lt;tt&amp;gt;tri_fusion&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Par exemple, pour trier dans un ordre décroissant :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let dec a n  = if a&amp;gt;=n then true&lt;br /&gt;
else false ;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
ou même plus simplement&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let dec = (&amp;gt;=) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour trier une liste de paires, il faut créer une fonction qui compare les seconds membres ;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let paire a n  = (snd a) &amp;lt;= (snd n)  ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
Ici, les paires seront triées selon le second membre dans l&#039;ordre croissant.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt;Question 8 ( Bonus )&amp;lt;/u&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Un algorithme de tri est dit stable quand il ne modifie pas l&#039;ordre relatifs des éléments &amp;quot;égaux&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Par exemple, on tri par ordre croissant du premier membre une liste de paires de float : [ ( 5 , 3 ) ; ( -2 , 8 ) ; ( -2 , 2 ) ; ( 5 , 8 ) ; ( 5 , -8 ) ]  &lt;br /&gt;
&lt;br /&gt;
non stable : &amp;lt;tt&amp;gt;[(-2, 2); (-2, 8); (5, -8); (5, 8); (5, 3)]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
stable : &amp;lt;tt&amp;gt;[(-2, 8); (-2, 2); (5, 3); (5, 8); (5, -8)]&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour qu&#039;un tri soit stable, la comparaison de deux éléments doit comprendre aussi le &amp;quot;=&amp;quot;, comme c&#039;est le cas pour les fonctions paire et dec.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD3== &amp;lt;br/&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Exercice 1 : les arbres binaires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt; Question 1 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type &#039;a arbre = Vide | Noeud of &#039;a*&#039;a arbre*&#039;a arbre ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 2 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
let rec taille a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; 1 + (taille g) + (taille d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction taille compte le nombre de noeuds que contient un arbre.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 3 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec applique f a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; Vide&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; Noeud(f e,applique f g,applique f d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction applique est équivalente à la fonction List.map&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 4 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec poids (f : &#039;a -&amp;gt; int) a = &lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; (f e) + (poids f g) + (poids f d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 5 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec reduit a o f =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; 0&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; let x = reduit g o f in&lt;br /&gt;
       			let y = reduit d o f in&lt;br /&gt;
                        f e x y ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction reduit est equivalente à la fonction List.fold_right pour le type des arbres.&lt;br /&gt;
&lt;br /&gt;
Réécriture de taille et poids :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec taille a = reduit a 0 (fun e x y -&amp;gt; 1 + x + y) ;;&lt;br /&gt;
let rec poids f a = reduit a 0 (fun e x y -&amp;gt; (f e) + (f x) + (f y)) ;; (*?????*)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 6 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec collecte a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; []&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; e::(collecte g)@(collecte d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction collecte récupère tous les éléments de l&#039;arbre et les renvoie sous forme d&#039;une liste.&lt;br /&gt;
&lt;br /&gt;
Avec la fonction reduit :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec collecte a = reduit a [] (fun e x y -&amp;gt; e::x@y) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 7 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec feuilles a =&lt;br /&gt;
   match a with&lt;br /&gt;
    	Vide -&amp;gt; []&lt;br /&gt;
       |Noeud(e,g,d) -&amp;gt; if (g=Vide &amp;amp;&amp;amp; d=Vide) then [e]&lt;br /&gt;
       			else (feuilles g)@(feuilles d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Avec reduit :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec feuilles a = reduit a [] (fun e x y -&amp;gt; if (x=[] &amp;amp;&amp;amp; y=[]) then [e]&lt;br /&gt;
					       else x@y) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;u&amp;gt; Exercice 2 : la tortue &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt; &amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt; Question 1 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type action = Forward of int | Left of int | SetPos of int*int | SetHeading of int | PenUp | Pendown ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 2 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt; &lt;br /&gt;
let rec ecrit (l:action list) (pen:bool) : bool =&lt;br /&gt;
   match l with&lt;br /&gt;
    	[] -&amp;gt; false&lt;br /&gt;
       |(Forward d)::l -&amp;gt; if (d=0 || pen=false) then ecrit l pen&lt;br /&gt;
                          else true &lt;br /&gt;
       |PenUp::l -&amp;gt; ecrit l false&lt;br /&gt;
       |PenDown::l -&amp;gt; ecrit l true&lt;br /&gt;
       | _ -&amp;gt; ecrit l pen ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
La fonction ecrit renvoie true si la tortue écrit qqch ou false sinon.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 3 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec pos (x:int) (y:int) (a:int) (l:action list) : ((int*int)int) =&lt;br /&gt;
   match l with&lt;br /&gt;
    	[] -&amp;gt; ((x,y),a)&lt;br /&gt;
       |PenUp::l |Pendown::l -&amp;gt; pos x y a l&lt;br /&gt;
       |(Left b)::l -&amp;gt; pos x y (a+b) l&lt;br /&gt;
       |(SetPos(x&#039;,y&#039;))::l -&amp;gt; pos x&#039; y&#039; a l&lt;br /&gt;
       |(SetHeading b)::l -&amp;gt; pos x y b l &lt;br /&gt;
       |(Forward d)::l -&amp;gt; pos (x+(sin a)*d) (y+(cos a)*d) a l ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;i&amp;gt; Question 5 &amp;lt;/i&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
type action = Forward of int | SetPos of int*int | SetHeading of int | Left of int | PenUp | Pendown | Repeat of int*action list ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Le TD4==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 1 : Petits exercices combinatoires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On commence par créer une fonction intermédiaire.&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supp&#039; x l =&lt;br /&gt;
   match l with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |b::f&#039;-&amp;gt; if (x=b) then supp&#039; x l&#039;&lt;br /&gt;
                        else b::supp&#039; x f&#039;;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supp l =&lt;br /&gt;
   match l with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |a::l&#039;-&amp;gt; a::supp supp&#039; a l&#039;;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 2 : Dictionnaires &amp;lt;/u&amp;gt;&amp;lt;/b&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Un dictionnaire est une liste de paires&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;b&amp;gt;Question 2 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insere c v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[(c,v)]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (c=c&#039;) then (c&#039;,v&#039;)::(insere c v d)&lt;br /&gt;
                               else (c,v)::d ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec supprime c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (c=c&#039;) then d&lt;br /&gt;
                               else (c&#039;,v&#039;)::(supprime c d) ;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec existe_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; false&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; (c=c&#039;) || existe_cle c d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec existe_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; false&lt;br /&gt;
      |(_,v&#039;)::d -&amp;gt; if (v=v&#039;) then true&lt;br /&gt;
                              else existe_val v d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec recherche_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; None&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; if (c=c&#039;) then Some c&#039;&lt;br /&gt;
                              else recherche_cle c d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* liste des valeurs de c par on peut avoir plusieurs cases, et donc plusieurs clés, avec une même valeur *)&lt;br /&gt;
let rec recherche_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(c&#039;,v&#039;)::d -&amp;gt; if (v=v&#039;) then c&#039;::(recherche_val v d)&lt;br /&gt;
                              else recherche_val v d;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Liste des clés *)&lt;br /&gt;
let rec liste_cle c d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt; []&lt;br /&gt;
      |(c&#039;,_)::d -&amp;gt; c&#039;::(liste_cle c d);;&lt;br /&gt;
&lt;br /&gt;
(* Liste des valeurs *)&lt;br /&gt;
let rec liste_val v d&lt;br /&gt;
   match d with&lt;br /&gt;
      []-&amp;gt;[]&lt;br /&gt;
      |(_,v&#039;)::d -&amp;gt; v&#039;::(liste_val v d);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
On peut également utiliser des fonctions existantes :&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
(* Liste des clés *)&lt;br /&gt;
let liste_cle d = List.map fst;;&lt;br /&gt;
&lt;br /&gt;
(* Liste des valeurs, attention aux doublons! *)&lt;br /&gt;
let liste_val d = suppr_doublons(List.map snd);;&lt;br /&gt;
  &amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 4 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec zip l1 l2&lt;br /&gt;
   match l1 l2 with&lt;br /&gt;
      [].[]-&amp;gt;[]&lt;br /&gt;
      |c::lc, v::lv -&amp;gt; (c,v)::(zip lc lv)&lt;br /&gt;
      |_,_ -&amp;gt; [];;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 5 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
On aurait pu utiliser une liste triée : si par exemple on cherche 12 et qu&#039;on en est à 14 dans la liste, on sait que 12 n&#039;y est pas. PB : ceci n&#039;empêche pas d&#039;aller à la fin de la liste si la valeur ou la clé recherchée est grande ... &amp;lt;br/&amp;gt;&lt;br /&gt;
Une recherche dichotomique est inefficace sur les listes ... &amp;lt;br/&amp;gt;&lt;br /&gt;
   =&amp;gt; dans la bibliothèque hash table de Caml, il existe un List.zip&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;&amp;lt;u&amp;gt; Exercice 3 : Arbres binaires &amp;lt;/u&amp;gt; &amp;lt;br/&amp;gt;&lt;br /&gt;
Question 1 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
La profondeur d&#039;un arbre binaire correspond au nombre d&#039;étage : on regarde à partir de la première racine et des sous arbres, on calcule la profondeur à gauche et la profondeur à droite, on prend la plus grande et on y ajoute 1. &lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec profondeur a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; 0&lt;br /&gt;
      |Noeud(_,g,d) -&amp;gt; 1 + max(profondeurg) (profondeurd);;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 2 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec equilibre a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; true&lt;br /&gt;
      |Noeud(_,g,d) -&amp;gt; if (profondeur g)=(profondeur d) || (profondeur g)=(profondeur d +1) || (profondeur g +1)=(profondeur d)&lt;br /&gt;
                          then (equilibre d)&amp;amp;&amp;amp;(equilibre g)&lt;br /&gt;
                          else false;;&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 3 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec present e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; false&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; e&#039;=e || present e g || present e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 4 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec present e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; false&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; if (e&#039;=e) then true&lt;br /&gt;
                                  else  if (e&amp;lt;e&#039;) then present e g&lt;br /&gt;
                                                  else present e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Question 5 &amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ocaml&amp;quot;&amp;gt;&lt;br /&gt;
let rec insere e a&lt;br /&gt;
   match a with&lt;br /&gt;
      Vide -&amp;gt; e&lt;br /&gt;
      |Noeud(e&#039;,g,d) -&amp;gt; if (e&amp;lt;e&#039;) then insere e g&lt;br /&gt;
                                  else insere e d;; &lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
blablabla&lt;br /&gt;
&lt;br /&gt;
blablablabla&lt;/div&gt;</summary>
		<author><name>Laurent corantin</name></author>
	</entry>
	<entry>
		<id>http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Discussion:INFO421_:_Programmation_fonctionnelle&amp;diff=3684</id>
		<title>Discussion:INFO421 : Programmation fonctionnelle</title>
		<link rel="alternate" type="text/html" href="http://os-vps418.infomaniak.ch:1250/mediawiki/index.php?title=Discussion:INFO421_:_Programmation_fonctionnelle&amp;diff=3684"/>
		<updated>2009-01-21T12:40:15Z</updated>

		<summary type="html">&lt;p&gt;Laurent corantin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Comment commencer une discussion ==&lt;br /&gt;
&lt;br /&gt;
Pour commencer une discussion, il suffit de cliquer sur le &#039;&#039;&#039;&amp;lt;tt&amp;gt;+&amp;lt;/tt&amp;gt;&#039;&#039;&#039; en haut de  la page. Vous pouvez alors rentrer un sujet de discussion et éditer le texte comme pour le wiki.&lt;br /&gt;
&lt;br /&gt;
C&#039;est mieux de signer vos intervention en utilisant l&#039;avant dernier bouton d&#039;édition, ou avec &amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;--~~~~&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
:Pour répondre, il faut « modifier » la section correspondante...&lt;br /&gt;
:Par soucis de visibilité, il est parfois préférable de rajouter une marge à gauche (comme ici). Pour faire ça, il faut commencer votre ligne par un «&amp;lt;tt&amp;gt;:&amp;lt;/tt&amp;gt;». (Ou un «&amp;lt;tt&amp;gt;::&amp;lt;/tt&amp;gt;»...)&lt;br /&gt;
&lt;br /&gt;
--[[Utilisateur:Hyvernat|Hyvernat]] 12 janvier 2009 à 13:47 (CET)&lt;br /&gt;
&lt;br /&gt;
== Inscription sur le Wiki ==&lt;br /&gt;
&lt;br /&gt;
Voila, c&#039;est juste pour dire que je me suis inscrit...&lt;br /&gt;
&lt;br /&gt;
--[[Utilisateur:Hyvernat|Hyvernat]] 21 janvier 2009 à 11:01 (CET)&lt;br /&gt;
&lt;br /&gt;
coucou c&#039;est moi&lt;br /&gt;
&lt;br /&gt;
Inscription sur le Wiki&lt;br /&gt;
--[[Utilisateur:LAYER|LAYER]] 21 janvier 2009 à 13:39 (CET)&lt;br /&gt;
&lt;br /&gt;
inscription terminée --[[Utilisateur:Laurent corantin|Laurent corantin]] 21 janvier 2009 à 13:40 (CET)&lt;/div&gt;</summary>
		<author><name>Laurent corantin</name></author>
	</entry>
</feed>