L'aire d'un triangle quelconque de côtés de longueurs $a$, $b$, $c$ est donnée par la formule
$\sqrt{p(p-a)(p-b)(p-c)}$ où $p$ désigne le demi-périmètre du triangle. Définissez une fonction
aire : float -> float -> float -> float
telle que aire a b c
est l'aire du triangle de côtés de longueur $a$, $b$, $c$. Vous ne devez pas calculer le demi-périmètre plusieurs fois.
Définissez une fonction est_rectangle : float -> float -> float -> bool
telle que est_rectangle a b c
renvoie true
si et seulement si le triangle de côtés $a$, $b$, $c$ est un triangle rectangle.
let aire a b c =
let p = (a +. b +. c) /. 2. in
sqrt (p *. (p -. a) *. (p -. b) *. (p -. c))
let est_rectangle a b c =
(aire a b c) *. (max (max a b) c) = a *. b *. c /. 2.
let est_rectangle a b c =
let [a'; b'; c'] = List.sort compare [a; b; c] in
a' * a' + b' * b' = c' * c'
Définissez de trois façons différentes la fonction max_liste : 'a list -> 'a
qui renvoie le plus grand élément d'une liste non vide quelconque (si la liste est vide, la fonction doit lever l'exception Invalid_argument "max_liste"
List.fold_left
On rappelle l'existence de la fonction max : 'a -> 'a -> 'a
.
let rec max_liste = function
| [] -> invalid_arg "max_liste"
| [a] -> a
| a::l -> max a (max_liste l) (* <- recurrence enveloppee *)
let max_liste l =
let rec f res = function
| [] -> res
| a::l -> f (max a res) l (* <- récursivité terminale (MIEUX!) *)
in match l with
| [] -> invalid_arg "max_liste"
| a::l -> f a l
let max_liste l =
match l with
| [] -> invalid_arg "max_liste"
| a::l2 -> begin
let res = ref a in
let p = ref l2 in
while !p <> [] do
res := max !res (List.hd !p);
p := List.tl !p
done;
!res
end
let max_liste l =
match l with
| [] -> invalid_arg "max_liste"
| a::l2 -> List.fold_left max a l2
La décomposition en facteurs premiers (dfp) d'un entier $n\geq 1$ est la suite de ces facteurs premiers listés dans l'ordre croissant. Par exemple
Définissez une fonction dfp_vers_entier : int list -> int
qui a une décomposition en facteur premier associe l'entier correspondant. Par exemple, dfp_vers_entier [2;2;5;7]
renvoie 140
.
Définissez la fonction inverse entier_vers_dfp : int -> int list
. Vous pourrez utiliser une boucle for ou while et un style impératif, ou vous pourrez compléter la fonction ci-dessous
let entier_vers_dfp n =
let rec f n m = match (n, m) with
| (1, _) -> []
| (n, p) when n mod p = 0 -> ...
| _ -> ....
in f n ...
Définissez la fonction dfp_produit : int list -> int list -> int list
qui prend les dfp de deux nombres et qui calcule la dfp de leur produit. Par exemple, dfp [2;2;5] [2;3;7]
renvoie [2;2;2;3;5;7]
.
let rec dfp_vers_entier = function
| [] -> 1
| a::l -> a * dfp_vers_entier l
let rec dfp_vers_entier = List.fold_left ( * ) 1
let entier_vers_dfp n =
let rec f n m = match (n, m) with
| (1, _) -> []
| (n, p) when n mod p = 0 -> p :: (f (n/p) p)
| _ -> f n (m+1)
in f n 2
let entier_vers_dfp n =
let acc = ref [] in
let m = ref 2 in
let n = ref n in
while !n <> 1 do
if !n mod !m = 0
then begin
acc := !m :: !acc;
n := !n / !m
end else begin
m := !m + 1
end
done;
List.rev !acc
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
Définissez la fonction taille : arbre -> int
qui calcule le nombre de noeuds internes d'un arbre (autrement dit le nombre d'opérations.
Définissez la fonction hauteur : arbre -> int
qui calcule la hauteur de l'arbre. On rappelle que la hauteur d'un arbre est longueur du plus long chemin de la racine à une feuille de l'arbre.
Définissez la fonction variables : arbre -> string list
qui calcule la liste des variables apparaissant sur les feuilles de l'arbre.
let rec taille = function
| Feuille(_) -> 0
| Noeud(_, arbre1, arbre2) -> taille arbre1 + taille arbre2
let rec hauteur = function
| Feuille(_) -> 0
| Noeud(_, arbre1, arbre2) -> max (hauteur arbre1) (hauteur arbre2)
let rec variables = function
| Feuille(Var x) -> [x]
| Feuille(_) -> []
| Noeud(_, arbre1, arbre2) -> (variables arbre1) @ (variables arbre2)
Ecrivez une fonction somme_fichier : string -> int
. L'entier somme_fichier nom_fichier
renvoyé par la fonction est la somme des lignes de nom_fichier
qui contiennent exactement un entier. Les autres lignes sont ignorées.
Par exemple, si toto.txt
est le fichier
30
il est 8 : 30
20
`
somme_fichier "toto.txt"
renverra 50
let somme_fichier fichier =
let ic = open_in fichier in
let acc = ref 0 in
let next_int () =
try int_of_string (input_line ic) with
| Failure(_) -> 0
in
try
while true do acc := !acc + next_int() done; assert false
with End_of_file -> close_in ic; !acc