TD 2 ASPECTS FONCTIONNELS DE CAML 1 Retour sur les fonctions Exercice 1 Une suite réelle correspond en Caml à une fonction de type int -> float. 1. Écrire une fonction somme : (int -> float) -> (int -> float) -> int -> float associant à deux suites u et v la suite u + v. 2. Écrire une fonction arith : float -> float -> int -> float telle que arith a b soit la suite arithmétique u de raison a et de terme initial u0 = b. Exercice 2 1. Écrire une fonction puis : (’a -> ’a -> ’a) -> ’a -> ’a -> int -> ’a telle que puis mul neutre x n calcule xn au sens de la multiplication définie par la fonction mul et l’élément neutre neutre. Cette fonction procédera par exponentiation rapide. 2. Définir à l’aide d’une application partielle de puis l’exponentiation rapide sur les entiers. 3. On décide de représenter une matrice ac db ∈ M2 (Z) par (a,b,c,d) : int * int * int * int a . On définit donc le type matrice = int * int * int * int. a. Écrire une fonction matr_mul : int -> matrice -> matrice -> matrice telle que matr_mul p x y calcule le produit de x et y modulo p (c’est-à-dire considérées comme Z des éléments de M2 pZ ). 109 Z . b. Calculer 01 11 dans 12345Z c. Si ( fn ) désigne la suite de Fibonacci, combien vaut f109 mod 12345 ? Combien de multiplications (approximativement, ou exactement si possible) a-t-on effectuées pour le calculer ? a. Ce n’est pas la bonne manière, mais ça fera l’affaire ici. 2 Listes Exercice 3 Écrire une fonction croissante : ’a list -> bool qui détermine si les éléments d’une liste sont rangés par ordre croissant. Exercice 4 1. OCaml fournit un opérateur infixe @ permettant de concaténer deux listes : # [1;2] @ [7;8];; Lycée du Parc –MPSI option informatique 1 TD 2 – Aspects fonctionnels de Caml - : int list = [1; 2; 7; 8] # [] @ [3.; 4.2];; - : float list = [3.; 4.2] a. Ré-implémenter cet opérateur sous la forme d’une fonction concat : ’a list -> ’a list -> ’a list. b. Lorsqu’on utilise cette fonction pour concaténer deux listes de longueurs respectives p et q, combien y a-t-il d’appels au constructeur :: ? 2. On souhaite écrire a une fonction reverse : ’a list -> ’a list qui "renverse" son argument (par exemple, reverse [1; 2; 3; 3] = [3; 3; 2; 1]). a. Écrire une version «naïve» de la fonction reverse en s’aidant de la fonction concat. Combien d’appels à :: cette fonction effectue-t-elle pour renverser une liste de longueur n ? b. Écrire une fonction aux : ’a list -> ’a list -> ’a list telle que aux l1 l2 = (reverse l1) @ l2. On n’utilisera pas la fonction concat (ni @) et l’on fera en sorte que le nombre d’appels de aux à :: soit de l’ordre de la longueur de l1. c. En déduire une version efficace de reverse. a. Cette fonction existe déjà en Caml : c’est List.rev. Exercice 5 1. Écrire une fonction indice : ’a list -> a -> int telle que indice l x renvoie l’indice de la première occurrence de x dans la liste l. Ainsi, si l = [2; 4; 3; 4; 1], indice l 4 renverra 1, indice l 1 renverra 4 et indice l 17 renverra une erreur (via failwith). 2. Écrire une fonction indices : ’a list -> a -> int list telle que indices l x renvoie la liste des occurrences de x dans l. Avec le l de la question précédente, on aura donc indices l 4 = [3; 1] et indices l 17 = []. On pourra utiliser une fonction auxiliaire de type ’a list -> ’a -> int list -> int -> int list. 3 Définitions de types Exercice 6 On définit l’ensemble Z = Z ∪ {−∞, +∞} auquel on étend les opérations usuelles (ainsi que l’ordre) sur Z. 1. Définir un type etendu permettant de représenter les éléments de Z. 2. Écrire une fonction inf : etendu -> etendu -> bool renvoyant true si son premier argument est inférieur ou égal au deuxième, false sinon. 3. a. Écrire une fonction somme : etendu -> etendu -> etendu faisant ce que son nom indique. On utilisera failwith pour traiter les cas indéterminés. b. Définir un type etendu_2 en ajoutant à etendu un constructeur NaN (Not a Number) et écrire une fonction somme_2 : etendu_2 -> etendu_2 -> etendu_2 qui traite correctement les cas indéterminés. 4. Écrire la fonction produit : etendu_2 -> etendu_2 -> etendu_2. 5. On s’intéresse dans cette question aux intervalles de Z. On ne s’autorise donc pas les intervalles du type ~−∞, b (par exemple). a. Définir un type intervalle permettant de représenter un tel intervalle. On pourra commencer par définir un type borne à partir du type int . b. Écrire une fonction inter : intervalle list -> intervalle calculant l’intersection d’une liste d’intervalles. Il est fortement conseillé de commencer par écrire une ou plusieurs fonctions auxiliaires. Lycée du Parc – MPSI option informatique 2