TD 2 (extra) 1 Listes

publicité
Licence 3, semestre 5, 2013–2014
Programmation Fonctionnelle
TD 2 (extra)
1
Listes
Exercice 1 (Récursion Terminale vs Récursion Non-terminale) :
Écrire des fonctions suivantes sur les listes.
– length : calcule la longueur d’une liste.
Exemple : length ["let" ;"toto" ;"42"; "hello"] = 4
length [true, false, false, true, true, false] = 6.
Donner une version non-terminale, puis une version terminale.
– list sigma : calcule la somme des éléments d’une liste d’entiers.
Exemple : list sigma [1 ;2 ;3] = 6.
Donner une version non-terminale, puis une version terminale.
– make n v : crée une liste de taille n initialisée avec la valeur v.
Exemple : make 3 "42" = ["42"; "42"; "42";]
Donner une version non-terminale, puis une version terminale.
– init n f : crée une liste de taille n initialisée à l’aide de la fonction f de
telle manière que la i-ème élément de la liste est égal à f i (pour i = 0 ..
(n-1)) .
Exemple : init 3 (fun i -> i) = [0; 1; 2]
Donner une version non-terminale, puis une version terminale.
– range k m : crée une liste contenant des entiers de k à m dans l’ordre
croissant. (si k > m , renvoie une liste vide)
Exemple : range 2 5 = [2 ;3; 4; 5].
Exercice 2 (Fonctions de la Bibliothèque Standard List) :
o mem : détermine si une liste contient une valeur donnée.
Exemple : mem 27 [12 ;27 ;1] = true, mem 3 [12 ;27 ;1] = false.
o append : concatène deux listes.
Exemple : append [1 ;2 ;3] [4 ;5] = [1 ;2 ;3 ;4 ;5].
Donner uniquement une version non-terminale.
o flatten : aplanir d’un niveau une liste de listes.
Exemple : flat [[2] ;[] ;[3 ;4 ;5]] = [2 ;3 ;4 ;5].
o map : la fonction telle que map f [a1 ;... ;an ] = [f(a1 ) ;... ;f(an )].
o exist : teste si au moins un des éléments de la liste satisfait une condition
passée en argument.
Exemple : exist (fun x -> if x = 0 then true else false) [1;2;0;4]
= true
1
Exercice 3 (palindromes) :
Écrire des fonctions suivantes sur les listes.
– last : trouve le dernier élément d’une liste. Si la liste est vide, lever l’exception Empty list définie précédemment.
Exemple : last [12 ;27 ;14] = 14
– drop last : renvoie la liste passée en argument privée du dernier élément.
Exemple : drop last [12 ;27 ;14] = [12 ;27]
– palindrome : teste si la liste passée en en argument est un palindrome
Exemple : palindrome [] = true, palindrome [1 ;2] = false, palindrome
[1 ;2 ;3 ;2 ;1] = true
Donner une version non-terminale (en utilisant les deux fonctions précédentes).
Quelle est la complexité de la solution ?
o rev : inverse l’ordre des éléments d’une liste.
Exemple : rev [1 ; 2 ; 3] = [3 ; 2 ; 1].
Donner une version non-terminale (en utilisant les deux fonctions précédentes
last et drop last). Quelle est la complexité de la solution ? Donner une
version terminale. Quelle est la complexité maintenant ?
– palindrome : Donner une version de palindrome non-terminale, en utilisant la fonction rev définie précédemment). Quelle est la complexité de
la solution ?
Exercice 4 (tri par insertion) :
Dans cet exercice, nous allons écrire le tri par insertion, sous la forme d’une
fonction opérant sur des listes d’entiers, c’est-à-dire ayant le type int list ->
int list.
1. Écrire une fonction insertion : int -> int list -> int list qui insère
un élément dans une liste d’entiers supposée triée en ordre croissant.
2. Écrire une fonction insertion sort : int list -> int list qui réalise
le tri par insertion d’une liste d’entiers. On rappelle que cela consiste à
extraire le premier élément de la liste, à trier récursivement le reste de la
liste, puis à insérer l’élément isolé (avec la fonction insertion).
3. Pour tester votre fonction de tri, écrivez une fonction
is sorted : int list -> bool qui retourne true si la liste passée en
argument est triée dans l’ordre croissant
Exercice 5 (tri rapide) :
Dans cet exercice, nous allons écrire le tri rapide (Quicksort) inventé par le
chercheur britannique C.A.R. Hoare.
1. Écrire une fonction partition : int -> int list -> int list * int
list qui prend en argument un entier x et une liste d’entiers l et renvoie
une paire de listes (l1,l2) telle que l1 (resp. l2) contient les éléments
de l plus petits (resp. plus grands) que x.
2
2. Écrire une fonction quicksort : int list -> int list réalisant le tri
rapide (quicksort). On rappelle que le principe consiste à isoler un élément
particulier de la liste (ici le premier), à partionner les éléments restants
en utilisant la fonction partition ci-dessus, à trier récursivement les deux
listes obtenues, et enfin à recoller les morceaux. Pour cette dernière étape
on pourra utiliser la fonction de bibliothèque List.append qui effectue la
concaténation de deux listes (elle se note également @ de manière infixe).
2
Ordre Supérieur
1. Écrire une fonction forall : (int -> bool) -> int array -> bool telle
que forall p t vérifie que p t.(i) renvoie bien true pour toutes les
cases i de t.
2. Qu’est-ce qui est affiché dans le terminal après avoir tapé la déclaration
suivante dans le top-level ?
# let rec test1 x =
let f = print_string "."; fun y -> y - 1 in
if x = 0 then 1 else test1 (f x) ;;
Même question après avoir tapé l’expression suivante :
# test1 4;;
3. Comparer vos réponses à la question précédente si on considère maintenant
la déclaration suivante :
# let rec test2 =
let f = print_string "."; fun y -> y - 1 in
fun x -> if x = 0 then 1 else test2 (f x) ;;
et l’expression suivante
# test3 4;;
4. Donner le type des fonctions suivantes :
let f = let x = ref 3 in fun () -> x
let g = fun () -> let x = ref 3 in x
5. Quelles sont les différences entre ces deux fonctions ?
6. Donner les résultats renvoyées (dans le top-level ) par les déclarations et/ou
expressions suivantes :
#
#
#
#
#
let a = f () ;;
let b = f () ;;
a = b ;;
a == b ;;
incr a; !b ;;
3
#
#
#
#
#
let c = g () ;;
let d = g () ;;
c = d ;;
c == d ;;
incr c; !d ;;
7. Soit la fonction plus définie de la manière suivante :
# let plus x y = x+y ;;
val plus : int -> int -> int = <fun>
Quelle différence y-a-t’il avec la déclaration suivante ?
# let plus (x, y) = x+y ;;
4
Téléchargement