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
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
(**********************************************************************)
(* Arbres n-aires *)
(**********************************************************************)
(** Arbre avec un nombre quelconque de fils *)
type 'a arbre_n = Feuille of 'a | Noeud of 'a arbre_n list
let a1 = Feuille 1
let a2 = Feuille 2
let a3 = Noeud []
let a4 = Noeud [ a1 ]
let a5 = Noeud [ a1; a2 ]
let a6 = Noeud [ a1; a2; a3; a4; a5 ]
let a_vide_1 = Noeud []
let a_vide_2 = Noeud [ Noeud [] ]
(* Le type de ces arbres vide est 'a arbre_n. En effet, comme ces arbres ne
contiennent pas d'éléments ils peuvent être vus comme des arbresavec ce qu'on
veut comme type d'élément. *)
let rec hauteur (a : 'a arbre_n) : int =
match a with Feuille _ -> 1 | Noeud l -> hauteur_foret l + 1
and hauteur_foret (l : 'arbre_n list) : int =
match l with
| [] -> 0
| a :: l' -> max (hauteur a) (hauteur_foret l')
;;
assert (hauteur a1 = 1);;
assert (hauteur a3 = 1);;
assert (hauteur a4 = 2);;
assert (hauteur a5 = 2);;
assert (hauteur a6 = 3)
(**
Renvoie une liste contenant tous les éléments de l'arbre
@param a: l'arbre
@return la liste de ses éléments
*)
let list_of_arbre (a : 'a arbre_n) : 'a list =
let rec list_of_arbre_aux (a : 'a arbre_n) (acc : 'a list) : 'a list
=
match a with
| Feuille x -> x :: acc
| Noeud f -> list_of_foret f acc
and list_of_foret (f : 'a arbre_n list) (acc : 'a list) : 'a list =
match f with
| [] -> acc
| a :: f' -> list_of_arbre_aux a (list_of_foret f' acc)
in
list_of_arbre_aux a []
;;
assert (list_of_arbre a1 = [ 1 ]);;
assert (list_of_arbre a4 = [ 1 ]);;
assert (list_of_arbre a5 = [ 1; 2 ]);;
assert (list_of_arbre a6 = [ 1; 2; 1; 1; 2 ])
(**
[minimum arbre] est le plus grand élément de arbre si arbre en contient au moins 1.
@param arbre l'arbre dans lequel on cherche le minimum
@return None si l'arbre ne contient pas d'élément, ou sinon Some m avec m le plus petit élément de l'arbre
*)
let rec minimum (arbre : 'a arbre_n) : 'a option =
match arbre with
| Feuille x -> Some x
| Noeud la -> minimum_foret la
(**
[minimum_foret l] donne l'élément minimal que l'on peut trouver dans une forêt
@param l la forêt
@return None si la forêt ne contient pas d'élément ou sinon Some m où m est le plus petit élément de la forêt
*)
and minimum_foret (la : 'a arbre_n list) : 'a option =
match la with
| [] -> None
| a :: la' -> (
match minimum_foret la' with
| None -> minimum a
| Some n -> (
match minimum a with
| None -> Some n
| Some n' -> Some (min n n')))
;;
assert (minimum a1 = Some 1);;
assert (minimum a3 = None);;
assert (minimum a4 = Some 1);;
assert (minimum a5 = Some 1);;
assert (minimum a6 = Some 1)
(**
[reduce f a] renvoie:
- None si a ne contient aucun élément
- Some x si a contient un seul élément x
- Some x où x est le résultat de la combinaison des éléments de a en utilisant f
@param f la fonction de combinaison des éléments
@param a l'arbre qui contient les éléments
*)
let rec reduce (f : 'a -> 'a -> 'a) (arbre : 'a arbre_n) : 'a option =
match arbre with Feuille x -> Some x | Noeud l -> reduce_foret f l
(**
[reduce_foret f l] renvoie:
- None si l (en tant que forêt) ne contient aucun élément
- Some x si l contient un seul élément x
- Some x où x est le résultat de la combinaison des éléments de l en utilisant f
@param f la fonction de combinaison des éléments
@param la forêt qui contient les éléments
*)
and reduce_foret (f : 'a -> 'a -> 'a) (la : 'a arbre_n list) :
'a option =
match la with
| [] -> None
| a :: la' -> (
match reduce_foret f la' with
| None -> reduce f a
| Some n -> (
match reduce f a with
| None -> Some n
| Some n' -> Some (f n n')))
;;
assert (reduce min a1 = Some 1);;
assert (reduce min a3 = None);;
assert (reduce min a4 = Some 1);;
assert (reduce min a5 = Some 1);;
assert (reduce min a6 = Some 1);;
assert (reduce ( + ) a1 = Some 1);;
assert (reduce ( + ) a3 = None);;
assert (reduce ( + ) a5 = Some 3);;
assert (reduce ( + ) a6 = Some 7)
(**********************************************************************)
(* Files (FIFO) implémentées avec deux listes *)
(**********************************************************************)
type 'a fifo = Fifo of ('a list * 'a list)
(** File vide *)
let empty_fifo : 'a fifo = Fifo ([], [])
(**
[push_fifo e f] Ajoute e dans f
@param e l'élément a ajouter
@param f la fifo dans laquelle on veut ajouter l'élément
@return la fifo contenant les éléments de f puis e
*)
let push_fifo (e : 'a) (f : 'a fifo) : 'a fifo =
match f with Fifo (l1, l2) -> Fifo (e :: l1, l2)
let f1 = push_fifo 1 empty_fifo
let f2 = push_fifo 2 f1
let f3 = push_fifo 3 f2
let f4 = push_fifo 4 f3;;
assert (f1 = Fifo ([ 1 ], []));;
assert (f2 = Fifo ([ 2; 1 ], []));;
assert (f3 = Fifo ([ 3; 2; 1 ], []));;
assert (f4 = Fifo ([ 4; 3; 2; 1 ], []))
(**
[push_list_fifo l f] ajoute les éléments de l à la file f
@param l les éléments à ajouter
@param f la file dans laquelle ajouter les éléments
@return la file contenant les éléments de f puis les éléments de l
*)
let rec push_list_fifo (l : 'a list) (f : 'a fifo) : 'a fifo =
match l with
| [] -> f
| x :: l' -> push_list_fifo l' (push_fifo x f)
;;
assert (push_list_fifo [] empty_fifo = empty_fifo);;
assert (push_list_fifo [] f2 = f2);;
assert (push_list_fifo [ 1 ] empty_fifo = f1);;
assert (push_list_fifo [ 3; 4 ] f2 = f4);;
assert (push_list_fifo [ 1; 2; 3; 4 ] empty_fifo = f4)
(**
Fonction utilitaire transférant tous les éléments de la liste de gauche dans
celle de droite en en renversant l'ordre au passage.
*)
let rec transfert_fifo (f : 'a fifo) : 'a fifo =
match f with
| Fifo ([], l2) -> Fifo ([], l2)
| Fifo (x :: l1, l2) -> transfert_fifo (Fifo (l1, x :: l2))
;;
assert (transfert_fifo f4 = Fifo ([], [ 1; 2; 3; 4 ]));;
assert (transfert_fifo f1 = Fifo ([], [ 1 ]))
(**
[pop_fifo f] renvoie le premier élément de f s'il y en a un, ainsi que la file contenant le reste des éléments de f.
@param f la file dans laquelle on veut prendre un élément
@return (f',r) où
- f' est la file contenant les éléments de f sauf le premier
- r est Some x si f a pour premier élément x ou bien None si f est vide
*)
let pop_fifo (f : 'a fifo) : 'a fifo * 'a option =
match f with
| Fifo (l1, []) -> (
match transfert_fifo f with
| Fifo (_, []) -> (Fifo ([], []), None)
| Fifo (_, x :: l2') -> (Fifo ([], l2'), Some x))
| Fifo (l1, x :: l2') -> (Fifo (l1, l2'), Some x)
;;
assert (pop_fifo empty_fifo = (empty_fifo, None));;
assert (pop_fifo f1 = (empty_fifo, Some 1));;
assert (pop_fifo f2 = (Fifo ([], [ 2 ]), Some 1));;
assert (pop_fifo (fst (pop_fifo f2)) = (empty_fifo, Some 2))
(**
Renvoie tous les éléments de la file dans l'ordre de celle-ci
@param f la file dont on veut les éléments
@return une liste contenant les éléments de f dans l'ordre
*)
let rec pop_all_fifo (f : 'a fifo) : 'a list =
match pop_fifo f with
| _, None -> []
| f', Some x -> x :: pop_all_fifo f'
;;
assert (pop_all_fifo empty_fifo = []);;
assert (pop_all_fifo f1 = [ 1 ]);;
assert (pop_all_fifo f4 = [ 1; 2; 3; 4 ]);;
(* Un test mélangeant les opérations de push et de pop de la file *)
assert (
pop_all_fifo (push_list_fifo [ 3; 4 ] (fst (pop_fifo f2)))
= [ 2; 3; 4 ])