Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
(* LIFPF TP3 Récursion sur les arbres *)
(**********************************************************************)
(* Arbres binaires *)
(**********************************************************************)
(**
Arbres binaires avec feuilles vides,
le contenu est seulement sur les noeuds.
*)
type arbre_bin = ABVide | ABNoeud of int * arbre_bin * arbre_bin
(* Quelques arbres pour tester *)
let ab1 = ABNoeud (3, ABVide, ABVide)
let ab2 = ABNoeud (5, ab1, ABVide)
let ab3 = ABNoeud (7, ABVide, ab1)
let ab4 = ABNoeud (11, ab2, ab3)
(**
Taille d'un arbre binaire.
@param a l'arbre dont on veut calculer la taille
@return le nombre d'int stockés dans l'arbre
*)
let rec taille_ab (a : arbre_bin) : int =
match a with
| ABVide -> 0
| ABNoeud (_, fg, fd) -> 1 + taille_ab fg + taille_ab fd
;;
assert (taille_ab ab1 = 1);;
assert (taille_ab ab2 = 2);;
assert (taille_ab ab3 = 2);;
assert (taille_ab ab4 = 5)
(**
Fait le produit des éléments d'un arbre binaire.
Un arbre vide aura 1 comme produit
@param a l'arbre dont on veut faire le produit des éléments
@return le produit (1 pour l'arbre vide)
*)
let rec produit_ab (a : arbre_bin) : int =
match a with
| ABVide -> 1
| ABNoeud (n, fg, fd) -> n * produit_ab fg * produit_ab fd
;;
assert (produit_ab ABVide = 1);;
assert (produit_ab ab1 = 3);;
assert (produit_ab ab2 = 15);;
assert (produit_ab ab3 = 21);;
assert (produit_ab ab4 = 3465)
(**
Construit la liste des éléments d'un arbre binaire. Les éléments sont produits
dans l'ordre de parcours infix, c'est à dire les éléments du fils gauche puis
l'élément du noeud puis ceux fils droit.
@param a l'arbre binaire dont on veut les éléments
@return la liste des éléments de l'arbre
*)
let rec list_of_arbre_bin (a : arbre_bin) : int list =
match a with
| ABVide -> []
| ABNoeud (n, fg, fd) ->
(* On peut aussi utiliser la fonction concatene du TP2 *)
list_of_arbre_bin fg @ (n :: list_of_arbre_bin fd)
;;
assert (list_of_arbre_bin ABVide = []);;
assert (list_of_arbre_bin ab1 = [ 3 ]);;
assert (list_of_arbre_bin ab2 = [ 3; 5 ]);;
assert (list_of_arbre_bin ab3 = [ 7; 3 ]);;
assert (list_of_arbre_bin ab4 = [ 3; 5; 11; 7; 3 ])
(**
Insère un élément dans un arbre binaire de recherche.
@param e l'élément à insérer
@param a l'arbre dans lequel on fait l'insersion
@return un arbre binaire de recherche contenant les éléments de a ainsi que e
*)
let rec insere_arbre_bin_recherche (e : int) (a : arbre_bin) : arbre_bin =
match a with
| ABVide -> ABNoeud (e, ABVide, ABVide)
| ABNoeud (x, fg, fd) ->
if e < x then ABNoeud (x, insere_arbre_bin_recherche e fg, fd)
else ABNoeud (x, fg, insere_arbre_bin_recherche e fd)
let abr1 = insere_arbre_bin_recherche 7 ABVide
let abr2 = insere_arbre_bin_recherche 5 abr1
let abr3 = insere_arbre_bin_recherche 3 abr2
let abr4 = insere_arbre_bin_recherche 11 abr3;;
assert (list_of_arbre_bin abr1 = [ 7 ]);;
assert (list_of_arbre_bin abr2 = [ 5; 7 ]);;
assert (list_of_arbre_bin abr3 = [ 3; 5; 7 ]);;
assert (list_of_arbre_bin abr4 = [ 3; 5; 7; 11 ])
(**
Créée un arbre binaire de recherche contenant les éléments de la liste
@param l la liste contenant les éléments à placer dans l'arbre à créer
@return l'arbre binaire de recherche contenant les éléments de l
*)
let rec arbre_bin_rech_of_int_list (l : int list) : arbre_bin =
match l with
| [] -> ABVide
| x :: l' -> insere_arbre_bin_recherche x (arbre_bin_rech_of_int_list l')
;;
assert (list_of_arbre_bin (arbre_bin_rech_of_int_list []) = []);;
assert (list_of_arbre_bin (arbre_bin_rech_of_int_list [ 3 ]) = [ 3 ]);;
assert (list_of_arbre_bin (arbre_bin_rech_of_int_list [ 3; 5 ]) = [ 3; 5 ]);;
assert (list_of_arbre_bin (arbre_bin_rech_of_int_list [ 5; 3 ]) = [ 3; 5 ]);;
assert (
list_of_arbre_bin (arbre_bin_rech_of_int_list [ 1; 2; 3; 4 ]) = [ 1; 2; 3; 4 ])
;;
assert (
list_of_arbre_bin (arbre_bin_rech_of_int_list [ 4; 2; 1; 3 ]) = [ 1; 2; 3; 4 ])
(**
Trie une list d'int en utilisant un arbre binaire de recherche
@param l la liste à trier
@return la liste triée
*)
let tri_abr (l : int list) : int list =
list_of_arbre_bin (arbre_bin_rech_of_int_list l)
;;
assert (tri_abr [] = []);;
assert (tri_abr [ 3 ] = [ 3 ]);;
assert (tri_abr [ 3; 5 ] = [ 3; 5 ]);;
assert (tri_abr [ 5; 3 ] = [ 3; 5 ]);;
assert (tri_abr [ 1; 2; 3; 4 ] = [ 1; 2; 3; 4 ]);;
assert (tri_abr [ 4; 2; 1; 3 ] = [ 1; 2; 3; 4 ])
(**********************************************************************)
(* Expressions arithmétiques et variables *)
(**********************************************************************)
(**
Type représentant les opérateurs binaires.
*)
type binop = Plus | Moins | Mult | Div
(**
Expressions arithmétiques + let
*)
type expr =
| Cst of int
| Binop of binop * expr * expr
| Var of string
| Let of string * expr * expr
(** affichage **)
let rec string_of_expr (e : expr) : string =
let string_of_binop (b : binop) =
match b with Plus -> " + " | Moins -> " - " | Mult -> " * " | Div -> " / "
in
match e with
| Cst n -> string_of_int n
| Binop (op, l, r) ->
"(" ^ string_of_expr l ^ string_of_binop op ^ string_of_expr r ^ ")"
| Var x -> x
| Let (v, e1, e2) ->
"(let " ^ v ^ " = " ^ string_of_expr e1 ^ " in " ^ string_of_expr e2 ^ ")"
(** Erreurs *)
type eval_err = DivZero | VarNonDef
(** Résultats: int ou erreur *)
type resultat = Ok of int | Err of eval_err
(**
Évalue une expression dans un environnement
*)
let rec eval_expr (e : expr) (env : (string * int) list) : resultat =
match e with
| Cst n -> Ok n
| Binop (op, e1, e2) -> (
match (eval_expr e1 env, eval_expr e2 env) with
| Ok v1, Ok v2 -> (
match op with
| Plus -> Ok (v1 + v2)
| Moins -> Ok (v1 - v2)
| Mult -> Ok (v1 * v2)
| Div -> if v2 = 0 then Err DivZero else Ok (v1 / v2))
| Err e, _ -> Err e
| _, Err e -> Err e)
| Var x -> (
match List.assoc_opt x env with None -> Err VarNonDef | Some n -> Ok n)
| Let (x, e1, e2) -> (
match eval_expr e1 env with
| Ok v1 -> eval_expr e2 ((x, v1) :: env)
| Err e -> Err e)
let e1 = Cst 3
let e2 = Binop (Plus, Cst 3, Cst 5)
let e3 = Binop (Div, Cst 3, Cst 0)
let e4 = Let ("a", Cst 3, Binop (Moins, Var "a", Cst 3))
let e5 = Let ("a", Cst 3, Var "b");;
assert (eval_expr e1 [] = Ok 3);;
assert (eval_expr e2 [] = Ok 8);;
assert (eval_expr e3 [] = Err DivZero);;
assert (eval_expr e4 [] = Ok 0);;
assert (eval_expr e5 [] = Err VarNonDef);;
assert (eval_expr e5 [ ("b", 11) ] = Ok 11)
(**********************************************************************)