Skip to content

Commit 4e58ea6

Browse files
authored
Merge pull request mouredev#3283 from luishendrix92/main
#18 - OCaml
2 parents 8c9bafb + ef27766 commit 4e58ea6

File tree

1 file changed

+121
-0
lines changed

1 file changed

+121
-0
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
open Printf
2+
3+
(*****************************************************************************)
4+
(* *)
5+
(* Set Data Structure *)
6+
(* *)
7+
(* Sets are a {e finite collection} of {b unique} data with roots in *)
8+
(* mathematics. The way sets are implemented allow for logarithmic-time *)
9+
(* access at the cost of slower write times than an array. Sets don't *)
10+
(* guarantee element order and they can't be repeated, they must be unique *)
11+
(* and depending on the language, of same type (mostly). *)
12+
(* OCaml doesn't let you have sets of different types and the standard *)
13+
(* library implements them as functors, meaning, you need to pass a module *)
14+
(* to the [Set.Make] functor in order to get back a new module that is *)
15+
(* bound to the type that the passed module represent. Among the most *)
16+
(* popular modules to pass are [String], [Float], [Int], and [Char]. *)
17+
(* *)
18+
(* Set operations are: *)
19+
(* - Union (A ∪ B): A set composed of all the elements from sets A and B. *)
20+
(* - Intersection (A ∩ B): Elements of A and B that appear on both sets. *)
21+
(* - Symmetric difference (A Δ B): All the elements of A and B that don't *)
22+
(* appear on both at the same time. Ex: {1,2,3} Δ {4,2,6} = {1,3,4,6}. *)
23+
(* - Difference (A - B): The elements of A without the ones that also *)
24+
(* appear on B; basically, subtration. Ex: {9,1,4,7} - {1,7,5,2} = {9,4}. *)
25+
(* *)
26+
(*****************************************************************************)
27+
28+
module IntSet = Set.Make (Int)
29+
30+
let show_int_set s =
31+
if IntSet.is_empty s
32+
then ""
33+
else
34+
IntSet.to_list s
35+
|> List.map string_of_int
36+
|> String.concat ", "
37+
|> sprintf "{ %s }"
38+
;;
39+
40+
let tap str set =
41+
printf str (show_int_set set);
42+
set
43+
;;
44+
45+
(** [symm_diff a b] is the symmetric difference between set [a] and set [b].
46+
A symmetric difference can be described as the difference between the
47+
union of [a] and [b], and their intersection. *)
48+
let symm_diff a b = IntSet.diff (IntSet.union a b) (IntSet.inter a b)
49+
50+
let _ =
51+
let b_set = IntSet.of_list [ 5; 10; 6; 0 ] in
52+
let a_set =
53+
IntSet.empty
54+
|> tap "Empty set: %s\n"
55+
|> IntSet.add 8
56+
|> tap "After adding 1 element: %s\n"
57+
|> IntSet.add_seq (List.to_seq [ 1; 5; 10 ])
58+
(* NOTE: Adding elements to a certain position is irrelevant in an OCaml set
59+
as they can't guarantee insertion order since the elements get sorted. *)
60+
|> tap "After adding multiple elements: %s\n"
61+
|> IntSet.remove 8
62+
|> tap "After removing the number 8: %s\n"
63+
in
64+
printf
65+
"Union: A (%s) ∪ B (%s) = %s\n"
66+
(show_int_set a_set)
67+
(show_int_set b_set)
68+
(IntSet.union a_set b_set |> show_int_set);
69+
printf
70+
"Intersection: A (%s) ∩ B (%s) = %s\n"
71+
(show_int_set a_set)
72+
(show_int_set b_set)
73+
(IntSet.inter a_set b_set |> show_int_set);
74+
printf
75+
"Difference: B (%s) - A (%s) = %s\n"
76+
(show_int_set b_set)
77+
(show_int_set a_set)
78+
(IntSet.diff b_set a_set |> show_int_set);
79+
printf
80+
"Symmetric Difference: B (%s) Δ A (%s) = %s\n"
81+
(show_int_set a_set)
82+
(show_int_set b_set)
83+
(symm_diff a_set b_set |> show_int_set);
84+
printf
85+
"Is 0 an element of set B = %s? %b\n"
86+
(show_int_set b_set)
87+
(IntSet.mem 0 b_set);
88+
printf "Cardinality (elt. count) of set A: %d\n" (IntSet.cardinal a_set)
89+
;;
90+
91+
(* Output of [dune exec reto18]
92+
93+
Empty set: ∅
94+
After adding 1 element: { 8 }
95+
After adding multiple elements: { 1, 5, 8, 10 }
96+
After removing the number 8: { 1, 5, 10 }
97+
Union: A ({ 1, 5, 10 }) ∪ B ({ 0, 5, 6, 10 }) = { 0, 1, 5, 6, 10 }
98+
Intersection: A ({ 1, 5, 10 }) ∩ B ({ 0, 5, 6, 10 }) = { 5, 10 }
99+
Difference: B ({ 0, 5, 6, 10 }) - A ({ 1, 5, 10 }) = { 0, 6 }
100+
Symmetric Difference: B ({ 1, 5, 10 }) Δ A ({ 0, 5, 6, 10 }) = { 0, 1, 6 }
101+
Is 0 an element of set B = { 0, 5, 6, 10 }? true
102+
Cardinality (elt. count) of set A: 3
103+
*)
104+
105+
(*****************************************************************************)
106+
(* *)
107+
(* Implementation and Ordering *)
108+
(* *)
109+
(* Sets can be implemented in 2 ways: with a tree-like data structure and *)
110+
(* using a hash table. A binary properly balanced binary tree can give us *)
111+
(* logarithmic access times and the traversal is done in orderly manner. In *)
112+
(* OCaml's standard lib, [Set] is implemented with a binary tree and that's *)
113+
(* why the module we pass to the functor must have a comparator function *)
114+
(* called [compare]. If we were to implement a set that remembers insertion *)
115+
(* order we could add both to a linked list and a b-tree or hash bucket. *)
116+
(* It's worth noting that if we wanted a data structure to add stuff to *)
117+
(* either end (front/rear) or at a specific position then maybe we're better *)
118+
(* off with an array or a linked list which can be converted to a set at a *)
119+
(* later time anyway (getting rid of duplicates). *)
120+
(* *)
121+
(*****************************************************************************)

0 commit comments

Comments
 (0)