Finir le [TP1](../TP1/tp1.md) avant de commencer ce TP.
>>>>>>> Stashed changes
Le reste du TP consiste à travailler la récursion sur les listes.
Comme dans le TP précédent, on prendra soin:
- de donner le type des arguments et le type de retour de chaque fonction;
- de **donner le type** des arguments et le type de retour de chaque fonction;
- d'écrire le commentaire de description de la fonction **avant** d'écrire la fonction.
_Remarque:_ ajouter un commentaire au-dessus de la fonction n'est pas la même chose que d'écrire le commentaire avant d'écrire la fonction. N'oubliez pas: vous écrivez avant tout ce commentaire pour vous aider à écrire la fonction et ensuite seulement pour la documenter.
_Remarque:__ajouter_ un commentaire au-dessus de la fonction n'est pas la même chose que d'écrire le commentaire _avant_ d'écrire la fonction. N'oubliez pas: vous écrivez avant tout ce commentaire pour vous aider à écrire la fonction et ensuite seulement pour la documenter.
On prendra également soin d'écrire des tests pour chaque fonction en écrivant des expressions du type `ma_fonction valeur1 valeur2 = valeur attendue;;` et en vérifiant avec l'interpréteur que ces tests s'évaluent à `true`.
...
...
@@ -17,7 +20,7 @@ On prendra également soin d'écrire des tests pour chaque fonction en écrivant
Dans cette partie on souhaite implémenter des fonctions qui vont concaténer des listes.
### 1.1 Concaténation de 2 listes
### 1.1 Concaténation de deux listes
Implémenter la fonction `concatene` qui prend deux `int list` et renvoie la liste constituée des éléments de la première suivis des éléments de la seconde.
### 1.2 Concaténation (applatissement) d'une liste de liste
Implémenter la fonction `applatit` qui prend une `(int list) list` et renvoie la liste constituée de la concaténation des éléments de cette liste de liste. Cette fonction utilisera la fonction `concatene` codée auparavant.
Implémenter la fonction `applatit` qui prend une `(int list) list` et renvoie la liste constituée de la concaténation des éléments de cette liste de liste.
Cette fonction utilisera la fonction `concatene` codée auparavant.
Faire une deuxième version `applatit2` ayant la même spécification que `applatit` mais qui n'utilise pas `concatene`.
Faire une deuxième version `applatit2` ayant la même spécification que `applatit` mais qui n'utilise **pas**`concatene`.
Tester cette fonction avec les mêmes tests que `applatit`.
## 2. Retournement de liste
On souhaite implémenter une fonction `renverse` qui renverse une liste.
L'algorithme naïf pour faire une inversion de liste consiste à inverser la queue de liste et à concaténer la tête de liste à la fin de la queue renversée. Cet algorithme est cependant inefficace car il conduit à effectuer un nombre quadratique (en fonction de la taille de la liste initiale) d'ajouts en tête de liste à cause de l'opération de concaténation.
L'algorithme naïf pour faire une inversion de liste consiste à inverser la queue de liste et à concaténer la tête de liste à la fin de la queue renversée.
Cet algorithme est cependant inefficace car il conduit à effectuer un nombre _quadratique_ (en fonction de la taille de la liste initiale) d'ajouts en tête de liste à cause de l'opération de concaténation.
On veut donc implémenter un algorithme plus efficace qui ne fait qu'un nombre linéaire d'ajout en tête de liste.
Pour cela on code auparavant une version modifiée `renverse_ajoute` qui prend deux listes en argument et renvoie la première renversée concaténée à la seconde, par exemple
On veut donc implémenter un algorithme plus efficace qui ne fait qu'un nombre _linéaire_ d'ajouts en tête de liste.
Pour cela on code une version modifiée `renverse_ajoute` qui prend **deux** listes en argument et renvoie la première renversée concaténée à la seconde, par exemple
```ocaml
renverse_ajoute[1;2;3][4;5;6]=[3;2;1;4;5;6]
```
on peut remarquer les égalités suivantes sont vraies:
On remarque que les égalités suivantes sont vraies:
On peut aussi remarquer que `renverse` peut se coder très facilement à partir de `renverse_ajoute` puisque `renverse l = renverse_ajoute l []`.
Coder `renverse` et définissant `renverse_ajoute`.
Définir tout d'abord `renverse_ajoute` avant `renverse` et tester. Essayer ensuite d'intégrer la définition de `renverse_ajoute` à l'intégrieur de celle de renverse via un `let rec renverse_ajoute ... in ...`.
Coder `renverse` en définissant `renverse_ajoute`.
Définir tout d'abord `renverse_ajoute` avant `renverse` et tester. Essayer ensuite d'intégrer la définition de `renverse_ajoute` à l'intérieur de celle de renverse via un `let rec renverse_ajoute ... in ...`.
## 3. Tri par insersion
On code l'algorithme de tri par insersion qui consiste, pour chaque élément, à l'insérer à la bonne place dans le reste de la liste préalablement trié.
On code [l'algorithme de tri par insertion](https://fr.wikipedia.org/wiki/Tri_par_insertion) qui consiste, pour chaque élément, à l'insérer à la bonne place dans le reste de la liste préalablement triée.
### 3.1 Insersion dans une liste triée
### 3.1 Insertion dans une liste triée
On commence donc par coder une fonction `insersion` qui insère un élément dans une liste triée.
On commence donc par coder une fonction `insertion` qui insère un élément _à la bonne position_ dans une liste triée par ordre croissant.
On rappelle qu'une liste d'association est une liste de paires (clé, valeur). L'opération principale sur ces listes consiste à chercher la valeur associée à une clé si elle existe.
On rappelle qu'une liste d'association est _une liste de paires `(clé, valeur)`_. L'opération principale sur les listes d'association est de chercher la valeur associée à une clé, si elle existe.
Dans cette question on considèrera que les clé sont de type `int` et les valeurs de type `string`.
Dans cette question on considèrera que les clés sont de type `int` et les valeurs de type `string`.
### 4.1 Type résultat
...
...
@@ -108,13 +113,13 @@ Pour cela il faut essentiellement se poser la question des données éventuellem
### 4.2 Fonction de recherche
Coder la fonction `cherche` qui va chercher une clé dans une liste d'association et renvoyer la valeur associée lorsqu'elle existe.
Coder la fonction `cherche` qui va chercher une clé dans une liste d'association et renvoyer la valeur associée lorsqu'elle existe et utilisant le type `resultat`.
Bien penser à écrire des tests pour cette fonction.
## 5. Calculatrice en notation polonaise
On souhaite implémenter une calculatrice en notation polonaise, c'est à dire calculant le résultat d'expressions dans laquelle les opérateurs sont placés avant leur arguments.
On souhaite implémenter une calculatrice en notation polonaise, c'est-à-dire calculant le résultat d'expressions dans lesquelles les **opérateurs sont placés avant leur arguments**.
On donne quelques exemples dans le tableau suivant:
| Notation habituelle | Notation polonaise |
...
...
@@ -126,7 +131,8 @@ On donne quelques exemples dans le tableau suivant:
On peut remarquer que cette notation permet de se passer de parenthèses.
Avant d'évaluer ce type d'expressions il faut pouvoir les représenter. On va donc se munir d'un type pour représenter les opérateurs, d'un type représentant les éléments d'expression (c'est-à-dire un opérateur ou un nombre):
Avant d'évaluer ce type d'expressions il faut pouvoir les représenter.
On va donc se munir d'un type pour représenter les opérateurs, d'un type représentant les éléments d'expression (c'est-à-dire un opérateur ou un nombre):