Programmation fonctionnelle

Partiel

E. Lozes - lundi 4 novembre 2019

Durée : 2h


REMARQUES

  • LES NOTES DE COURS, TELEPHONES, ORDINATEURS, ETC SONT INTERDITS.
  • LES TIERS TEMPS BENEFICIENT D'UN BARÈME AMÉNAGÉ

Exercice 1 - Un exercice relativement facile (3 points)

Définissez une fonction einstein u v qui prend en argument deux vitesses et qui calcule leur somme avec la loi d'addition des vitesses en relativité restreinte.

$$ \mathsf{einstein}(u,v) = \frac{u+v}{1+\frac{uv}{c^2}} $$

où la vitesse de la lumière $c= 300000 km.s^{-1}$ est une constante que vous définirez en dehors de votre fonction.

Le type de la fonction doit être float -> float -> float, et non float * float -> float. Autrement dit, on attend une fonction "curryfiée", dans le style OCaml habituel.

Exercice 2 - Aplatissement de liste (4 points)

Définissez de quatre façons différentes la fonction flatten : 'a list list -> 'a list telle que flatten [l1; ... ln] renvoie la concaténation l1@...@ln. Par exemple, flatten [[1;2];[];[3]] renvoie [1;2;3].

  1. Utilisez une définition récursive "naturelle" mais enveloppée
  2. Utilisez une définition récursive terminale
  3. Utilisez une boucle for ou while
  4. Utilisez List.fold_left

Exercice 3 - Quadratfrei (4 points)

Un nombre entier $n\geq 1$ est dit quadratfrei s'il n'existe pas de nombre premier $p$ tel que $p^2$ divise $n$. Par exemple

  • $1$ est un quadratfrei
  • tout nombre premier est quadratfrei
  • $30=2\times3\times 5$ est quadratfrei
  • 4,9,12,18,... ne sont pas quadratfrei

Définissez une fonction est_quadratfrei : int -> bool qui permet de tester si un entier $n\geq 1$ est quadratfrei.

Exercice 4 - Module d'un nombre complexe (3 points)

On veut définir un type complexe qui permet de représenter un nombre complexe soit "en scalaire", avec sa partie réelle et sa partie imaginaire, soit "en polaire", avec son module et son argument. On introduit les types de données suivants.

type scalaire = {re:float; im:float}
type polaire = {mo:float; arg:float}
type complexe = 
| Scalaire of scalaire
| Polaire of polaire
  1. Définissez la fonction module_p : polaire -> float qui calcule le module d'un enregistrement de type polaire, autrement dit le contenu du champs mo.

  2. Définissez la fonction module_s : scalaire -> float qui calcule le module d'un enregistrement de type scalaire. On rappelle que si $x$ et $y$ sont les parties réelle et imaginaire d'un nombre complexe, alors son module est égal à $\sqrt{x^2+y^2}$.

  3. Définissez la fonction module_c : complexe -> float qui calcule le module d'un nombre complexe, représenté soit par ses coordonnées scalaires, soit par ses coordonnées polaires.

Exercice 5 - Arbres binaires d'expression (3 points)

On rappelle le type des arbres binaires d'expressions vu en cours

type arbre = 
  | Feuille of feuille
  | Noeud of operateur * arbre * arbre
and feuille = 
  | Const of int
  | Var of string
and operateur = PLUS | SUB | MULT | DIV

Question 5.1

Définissez la fonction nb_feuilles : arbre -> int qui calcule le nombre de feuilles d'un arbre.

Question 5.2

Définissez la fonction sans_div : arbre -> bool qui renvoie true si l'opérateur DIV n'apparait pas dans l'arbre.

Exercice 6 - Nombre de lignes d'un fichier (3 points)

Ecrivez une fonction wc : string -> int. L'entier wc nom_fichier renvoyé par la fonction est le nombre de lignes du fichier nom_fichier.

Pourquoi wc? : le nom de la fonction est tiré de l'utilitaire shell wc (word count) qui fait la même chose avec l'option -l (souvenir de L1?).


Mémo

In [1]:
sqrt 2. +. 3. ** 2. /. 3.
Out[1]:
- : float = 4.41421356237309492
In [2]:
type id = {nom: string; age: int}
let age id = id.age
Out[2]:
type id = { nom : string; age : int; }
Out[2]:
val age : id -> int = <fun>
In [3]:
List.hd [1;2;3]
Out[3]:
- : int = 1
In [10]:
List.tl [1;2;3]
Out[10]:
- : int list = [2; 3]
In [12]:
[1;2] @ [3;4]
Out[12]:
- : int list = [1; 2; 3; 4]
In [13]:
1::[2;3]
Out[13]:
- : int list = [1; 2; 3]

List.fold_left (++) x0 [x1;...;xn] renvoie (...(x0++x1)++...)++xn.

In [5]:
List.fold_left (^) "" ["hello"; " "; "world"; "!"]
Out[5]:
- : string = "hello world!"
In [6]:
let rec my_fold_left f x0 l = match l with
| [] -> x0
| x1::x2xn -> my_fold_left f (f x0 x1) x2xn
Out[6]:
val my_fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>
In [7]:
let r = ref 0
Out[7]:
val r : int ref = {contents = 0}
In [8]:
while !r <> 10 do r := !r + 1; print_int !r done
Out[8]:
- : unit = ()
In [9]:
let premiere_ligne fichier = 
  try 
    let ic = open_in fichier in
    let res = input_line ic in
    close_in ic;
    res
  with End_of_file -> invalid_arg "fichier vide!"
Out[9]:
val premiere_ligne : string -> string = <fun>