diff --git a/lab01/expo.ml b/lab01/expo.ml new file mode 100644 index 0000000..583095a --- /dev/null +++ b/lab01/expo.ml @@ -0,0 +1,114 @@ +(** [fact n] calculates the factorial of [n]; non tail recursive *) +let rec fact n = + if n = 0. then 1. + else n *. fact(n -. 1.);; + +(**/**) +let test_fact () = + assert (fact 0. = 1.); + assert (fact 3. = 6.); + assert (fact 5. = 120.) +(**/**) + +(** [fact_tr n] calculates the factorial of [n]; tail recursive *) +let fact_tr n = + let rec fact_tr' acc i = + if i = 0. then acc + else fact_tr' (i *. acc) (i -. 1.) + in + fact_tr' 1. n;; + +(**/**) +let test_fact_tr () = + assert (fact_tr 0. = 1.); + assert (fact_tr 3. = 6.); + assert (fact_tr 5. = 120.) +(**/**) + +(** [pow_tr a b] calculates [a] to the power of [b]; non tail recursive *) +let rec pow a b = + if b = 0. then 1. + else a *. pow a (b -. 1.);; + +(**/**) +let test_pow () = + assert (pow 0. 1. = 0.); + assert (pow 0. 5. = 0.); + assert (pow 1. 0. = 1.); + assert (pow 5. 0. = 1.); + assert (pow 1. 1. = 1.); + assert (pow 5. 1. = 5.); + assert (pow 2. 3. = 8.) +(**/**) + +(** [pow_tr a b] calculates [a] to the power of [b]; tail recursive *) +let pow_tr a b = + let rec pow_tr' acc i = + if i = 0. then acc + else pow_tr' (acc *. a) (i -. 1.) + in + pow_tr' 1. b;; + +(**/**) +let test_pow_tr () = + assert (pow_tr 0. 1. = 0.); + assert (pow_tr 0. 5. = 0.); + assert (pow_tr 1. 0. = 1.); + assert (pow_tr 5. 0. = 1.); + assert (pow_tr 1. 1. = 1.); + assert (pow_tr 5. 1. = 5.); + assert (pow_tr 2. 3. = 8.) +(**/**) + +(** [expo_tr n x] calculates the approximation of e to the power of [x]; + * with a max iteration detail of [n]; non tail recursive + * Require: [n] >= 1 + *) +let rec expo n x = + if n = 0 then 1. + else pow x (float_of_int n) /. fact (float_of_int n) +. + expo (n - 1) x;; + +(**/**) +let test_expo () = + let tolerance = 1e-6 in + let diff = abs_float (expo 20 1. -. exp 1.) in + assert (diff < tolerance); + let diff = abs_float (expo 20 2. -. exp 2.) in + assert (diff < tolerance); + let diff = abs_float (expo 20 3. -. exp 3.) in + assert (diff < tolerance) +(**/**) + +(** [expo_tr n x] calculates the approximation of e to the power of [x]; + * with a max iteration detail of [n]; tail recursive + * Require: [n] >= 1 + *) +let expo_tr n x = + let rec expo_tr' acc i = + if i = 0 then acc + else expo_tr' (acc +. pow_tr x (float_of_int i) /. + fact_tr (float_of_int i)) (i - 1) + in + expo_tr' 1. n;; + +(**/**) +let test_expo_tr () = + let tolerance = 1e-6 in + let diff = abs_float (expo_tr 20 1. -. exp 1.) in + assert (diff < tolerance); + let diff = abs_float (expo_tr 20 2. -. exp 2.) in + assert (diff < tolerance); + let diff = abs_float (expo_tr 20 3. -. exp 3.) in + assert (diff < tolerance) +(**/**) + +(**/**) +let run_all_tests () = + test_fact(); + test_fact_tr(); + test_pow(); + test_pow_tr(); + test_expo(); + test_expo_tr() +(**/**) diff --git a/lab01/lab1.ml b/lab01/lab1.ml new file mode 100644 index 0000000..aa1c705 --- /dev/null +++ b/lab01/lab1.ml @@ -0,0 +1,154 @@ +(** [reverse l] returns the reverse order of list [l]; non tail recursive *) +let rec reverse l = + match l with + | [] -> [] + | x :: xs -> reverse xs @ [x];; + +(**/**) +let test_reverse () = + assert (reverse [] = []); + assert (reverse [1] = [1]); + assert (reverse [1; 2] = [2; 1]) +(**/**) + +(** [reverse_tr l] returns the reverse order of list [l]; tail recursive *) +let reverse_tr l = + let rec reverse_tr' acc l = + match l with + | [] -> acc + | x :: xs -> reverse_tr' (x :: acc) xs + in + reverse_tr' [] l;; + +(**/**) +let test_reverse_tr () = + assert (reverse_tr [] = []); + assert (reverse_tr [1] = [1]); + assert (reverse_tr [1; 2] = [2; 1]) +(**/**) + +(** [zip l1 l2] combines elements from [l1] and [l2] into a + * new list of tuples; non tail recursive + *) +let rec zip l1 l2 = + match l1, l2 with + | [], _ | _, [] -> [] (* if l1 or l2 is empty, return empty *) + | x1 :: xs1, x2 :: xs2 -> + (x1, x2) :: zip xs1 xs2;; + +(**/**) +let test_zip () = + assert (zip [] [] = []); + assert (zip [1] [] = []); + assert (zip [] ['a'] = []); + assert (zip [1; 2; 3] ['a'; 'b'] = [(1, 'a'); (2, 'b')]); + assert (zip [1; 2; 3] ['a'; 'b'; 'c'] = [(1, 'a'); (2, 'b'); (3, 'c')]) +(**/**) + +(** [zip_tr l1 l2] combines elements from [l1] and [l2] into a + * new list of tuples; tail recursive + *) +let zip_tr l1 l2 = + let rec zip_tr' acc l1 l2 = + match l1, l2 with + | [], _ | _, [] -> reverse_tr acc (* if l1 or l2 is empty, return empty *) + | x1 :: xs1, x2 :: xs2 -> + zip_tr' ((x1, x2) :: acc) xs1 xs2 + in + zip_tr' [] l1 l2;; + +(**/**) +let test_zip_tr () = + assert (zip_tr [] [] = []); + assert (zip_tr [1] [] = []); + assert (zip_tr [] ['a'] = []); + assert (zip_tr [1; 2; 3] ['a'; 'b'] = [(1, 'a'); (2, 'b')]); + assert (zip_tr [1; 2; 3] ['a'; 'b'; 'c'] = [(1, 'a'); (2, 'b'); (3, 'c')]) +(**/**) + +(** [unzip l] takes in a list of tuples [l] where each tuple is + * a pair, we seperate the pairs (x, y) into sepeate lists, ([x], [y]) + * and return a tuple of both lists; non tail recursive *) +let rec unzip l = + match l with + | [] -> ([], []) + | (x, y) :: xys -> + let (l1, l2) = unzip xys in + x :: l1, y :: l2;; + +(**/**) +let test_unzip () = + assert (unzip [] = ([], [])); + assert (unzip [(1, 'a')] = ([1], ['a'])); + assert (unzip [(1, 'a'); (2, 'b')] = ([1; 2], ['a'; 'b'])) +(**/**) + +(** [unzip_tr l] takes in a list of tuples [l] where each tuple is + * a pair, we seperate the pairs (x, y) into sepeate lists, ([x], [y]) + * and return a tuple of both lists; tail recursive *) +let unzip_tr l = + let rec unzip_tr' (a1, a2) l = + match l with + | [] -> (a1, a2) + | (x, y) :: xys -> + unzip_tr' (x :: a1, y :: a2) xys + in + unzip_tr' ([], []) (reverse_tr l);; + +(**/**) +let test_unzip_tr () = + assert (unzip_tr [] = ([], [])); + assert (unzip_tr [(1, 'a')] = ([1], ['a'])); + assert (unzip_tr [(1, 'a'); (2, 'b')] = ([1; 2], ['a'; 'b'])) +(**/**) + +(** [dedup l] takes in a list [l] and collapses consecutive duplicated + * elements into a single element; non tail recursive *) +let rec dedup l = + match l with + | [] -> [] + | [x] -> l + | x :: y :: zs -> + if x = y then dedup (x :: zs) + else x :: dedup (y :: zs);; + +(**/**) +let test_dedup () = + assert (dedup [] = []); + assert (dedup [1] = [1]); + assert (dedup [1; 2] = [1; 2]); + assert (dedup [1; 1; 2; 2; 2; 1; 3; 3; 2] = [1; 2; 1; 3; 2]) +(**/**) + +(** [dedup l] takes in a list [l] and collapses consecutive duplicated + * elements into a single element; tail recursive *) +let dedup_tr l = + let rec dedup' acc l = + match l with + | [] -> acc + | [x] -> l + | x :: y :: zs -> + if x = y then dedup' (x :: acc) (x :: zs) + else x :: dedup' (x :: acc) (y :: zs) + in + dedup' [] l;; + +(**/**) +let test_dedup_tr () = + assert (dedup_tr [] = []); + assert (dedup_tr [1] = [1]); + assert (dedup_tr [1; 2] = [1; 2]); + assert (dedup_tr [1; 1; 2; 2; 2; 1; 3; 3; 2] = [1; 2; 1; 3; 2]) +(**/**) + +(**/**) +let run_all_tests () = + test_reverse(); + test_reverse_tr(); + test_zip(); + test_zip_tr(); + test_unzip(); + test_unzip_tr(); + test_dedup(); + test_dedup_tr(); +(**/**) diff --git a/lecture02/html/Length.html b/lecture02/html/Length.html new file mode 100644 index 0000000..7aa0b12 --- /dev/null +++ b/lecture02/html/Length.html @@ -0,0 +1,33 @@ + + +
+ + + + + + + +module Length:sig..end
returns the number of elements in the list l - non tail recursive
val length : 'a list -> int
+val test_length : unit -> unit
+val length_tr : 'a list -> intreturns the number of elements in the list l - tail recursive
val test_length_tr : unit -> unit
diff --git a/lecture02/html/index.html b/lecture02/html/index.html
new file mode 100644
index 0000000..89788da
--- /dev/null
+++ b/lecture02/html/index.html
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+| Length |
+ returns the number of elements in the list
+l - non tail recursive
+ |
L | |
| Length | +
+ returns the number of elements in the list
+l - non tail recursive
+ |
L | |
| length [Length] | +|
| length_tr [Length] | +
+ returns the number of elements in the list
+l - tail recursive
+ |
T | |
| test_length [Length] | +|
| test_length_tr [Length] | +
sig end
diff --git a/lecture02/lists.ml b/lecture02/lists.ml
new file mode 100644
index 0000000..c4f211f
--- /dev/null
+++ b/lecture02/lists.ml
@@ -0,0 +1,187 @@
+(*
+ if everything is fine, test functions
+ will return the unit value
+*)
+
+(** [length l] returns the number of elements in the list [l]; non tail recursive *)
+let rec length l =
+ match l with
+ | [] -> 0
+ | x :: xs -> 1 + length xs;;
+
+(**/**)
+let test_length () =
+ assert (length [] = 0);
+ assert (length [2] = 1);
+ assert (length [5; 7; 8;] = 3)
+(**/**)
+
+(** [length_tr l] returns the number of elements in the list [l]; tail recursive *)
+let length_tr l =
+ let rec lenth_tr' acc l =
+ match l with
+ | [] -> acc
+ | _ :: xs -> lenth_tr' (acc + 1) xs
+ in
+ lenth_tr' 0 l;;
+
+(**/**)
+let test_length_tr () =
+ assert (length_tr [] = 0);
+ assert (length_tr [2] = 1);
+ assert (length_tr [5; 7; 8;] = 3)
+(**/**)
+
+(** [reverse l] returns the reverse order of list [l]; non tail recursive *)
+let rec reverse l =
+ match l with
+ | [] -> []
+ | x :: xs -> reverse xs @ [x];;
+
+(**/**)
+let test_reverse () =
+ assert (reverse [] = []);
+ assert (reverse [1] = [1]);
+ assert (reverse [1; 2] = [2; 1])
+(**/**)
+
+(** [reverse_tr l] returns the reverse order of list [l]; tail recursive *)
+let reverse_tr l =
+ let rec reverse_tr' acc l =
+ match l with
+ | [] -> acc
+ | x :: xs -> reverse_tr' (x :: acc) xs
+ in
+ reverse_tr' [] l;;
+
+(**/**)
+let test_reverse_tr () =
+ assert (reverse_tr [] = []);
+ assert (reverse_tr [1] = [1]);
+ assert (reverse_tr [1; 2] = [2; 1])
+(**/**)
+
+(* list.rev is a built in reverse function *)
+
+(** [take n l] returns a list containing the first [n] elements of [l];
+ * return [] if (n <= 0); return [l] if [l has fewer elements than [n]];
+ * non tail recursive *)
+let rec take n l =
+ if n <= 0 then []
+ else
+ match l with
+ | [] -> []
+ | x :: xs -> x :: take (n - 1) xs
+
+(**/**)
+let test_take () =
+ assert (take 0 [1; 2; 3;] = []);
+ assert (take 3 [4; 5; 6; 7; 8; 9] = [4; 5; 6]);
+ assert (take 5 [1; 2; 3] = [1; 2; 3])
+(**/**)
+
+(** [take_tr n l] returns a list containing the first [n] elements of [l];
+ * return [] if (n <= 0); return [l] if [l has fewer elements than [n]];
+ * tail recursive *)
+let take_tr n l =
+ let rec take_tr' acc n l =
+ if n <= 0 then reverse_tr(acc)
+ else
+ match l with
+ | [] -> acc
+ | x :: xs -> x :: take_tr' (x :: acc) (n - 1) xs
+ in
+ take_tr' [] n l;;
+
+(**/**)
+let test_take_tr () =
+ assert (take_tr 0 [1; 2; 3;] = []);
+ assert (take_tr 3 [4; 5; 6; 7; 8; 9] = [4; 5; 6]);
+ assert (take_tr 5 [1; 2; 3] = [1; 2; 3])
+(**/**)
+
+(** [every_other l] returns a list consisting of every other element of [l]
+ * starting from the first element; non tail recursive *)
+let rec every_other l =
+ match l with
+ | x :: _ :: xs -> every_other xs
+ | _ -> l;;
+
+(**/**)
+let test_every_other () =
+ assert (every_other [] = []);
+ assert (every_other [1] = []);
+ assert (every_other [1; 2] = [2]);
+ assert (every_other [1; 2; 3] = [2]);
+ assert (every_other [1; 2; 3; 4] = [2; 4])
+(**/**)
+
+(** [every_other_tr l] returns a list consisting of every other element of [l]
+ * starting from the first element; tail recursive *)
+let every_other_tr l =
+ let rec every_other_tr' acc l =
+ match l with
+ | x :: _ :: xs -> every_other_tr' (x :: acc) xs
+ | _ -> reverse_tr acc
+ in
+ every_other_tr' [] l;;
+
+(**/**)
+let test_every_other_tr () =
+ assert (every_other_tr [] = []);
+ assert (every_other_tr [1] = []);
+ assert (every_other_tr [1; 2] = [2]);
+ assert (every_other_tr [1; 2; 3] = [2]);
+ assert (every_other_tr [1; 2; 3; 4] = [2; 4])
+(**/**)
+
+(** [sum l1 l2] returns a list consisting of the sum of corresponding integers
+ * in [l1] and [l2]; non tail recursive *)
+let rec sum l1 l2 =
+ match l1, l2 with (* this is a tuple of (l1, l2) *)
+ | [], _ | _, [] -> [] (* if l1 is empty or l2 is empty, return empty *)
+ | x1 :: xs1, x2 :: xs2 ->
+ (x1 + x2) :: sum xs1 xs2;;
+
+(**/**)
+let test_sum () =
+ assert (sum [] [] = []);
+ assert (sum [1] [] = []);
+ assert (sum [] [1] = []);
+ assert (sum [7] [8] = [15]);
+ assert (sum [7; 3] [8; 8] = [15; 11]);
+ assert (sum [7] [8; 8] = [15])
+(**/**)
+
+(** [sum_tr l1 l2] returns a list consisting of the sum of corresponding integers
+ * in [l1] and [l2]; tail recursive *)
+let sum_tr l1 l2 =
+ let rec sum_tr' acc l1 l2 =
+ match l1, l2 with
+ | [], _ | _, [] -> reverse_tr acc
+ | x1 :: xs1, x2 :: xs2 ->
+ sum_tr' ((x1 + x2) :: acc) xs1 xs2
+ in
+ sum_tr' [] l1 l2;;
+
+(**/**)
+let test_sum_tr () =
+ assert (sum_tr [] [] = []);
+ assert (sum_tr [1] [] = []);
+ assert (sum_tr [] [1] = []);
+ assert (sum_tr [7] [8] = [15]);
+ assert (sum_tr [7; 3] [8; 8] = [15; 11]);
+ assert (sum_tr [7] [8; 8] = [15])
+(**/**)
+
+(** [count_change amt denoms] returns the number of ways of breaking up [amt]
+ * into currencies with denominations specified by [denoms];
+ * Require: elements of [denoms] must be positive *)
+let rec count_change amt denoms =
+ if amt < 0 then 0
+ else if amt = 0 then 1
+ else
+ match denoms with
+ | [] -> 0
+ | d :: ds ->
+ count_change (amt - d) denoms + count_change amt ds;; (* use/not-use d *)
diff --git a/lecture02/notes02.ml b/lecture02/notes02.ml
new file mode 100644
index 0000000..7b4af4a
--- /dev/null
+++ b/lecture02/notes02.ml
@@ -0,0 +1,135 @@
+(*
+ ***** TUPLES *****
+ has a fixed number of elements
+*)
+let x = (1, 2.1, "hello");;
+
+(*
+ this is also a tuple, but this tuple
+ is a different type to the tuple above
+*)
+let y = (1, 2.1, "hello", "goodbye");;
+
+(*
+ function with tuple argument
+
+ accepts a tuple with 3 elements of int
+*)
+let add_tuple (x, y, z) = x + y + z;;
+
+(*
+ ***** PATTERN MATCHING *****
+ where x gets deconstructed into a, b, and c
+*)
+let (a, b, c) = x;;
+
+a;;
+b;;
+c;;
+
+(*
+ ***** LISTS *****
+
+ lists are semi-colon seperated values of the same type
+ lists are a recursive data type
+*)
+let nums = [1; 2; 3];; (* this is a valid list *)
+
+(*
+ warning -
+ this is valid syntax but this is a list with a single
+ element that is a tuple of 3 ints
+*)
+let nums = [1, 2, 3];;
+(* results in - list : [(1, 2, 3)] *)
+
+(*
+ since lists are recursive data structures
+ we can add elements to the front of the list
+ as seen below
+
+ this operation is called cons
+*)
+2 :: (1 :: []);;
+2 :: 1 :: [];;
+
+(*
+ [1; 2; 3] === 1 :: 2 :: 3 :: [];;
+*)
+
+(* list of lists *)
+[[1; 2]; [3; 4]];;
+
+(* list concatonation *)
+[1; 2] @ [3; 4];;
+
+[];;
+(*
+ results in - : 'a list = []
+
+ where 'a means its a type variable
+ since lists are generic
+*)
+
+let l = [[1; 2]; [3]; []];;
+
+(*
+ pattern matching lists to extract 3
+ pattern matching must be exhaustive
+*)
+let [_; [x]; _] = l;;
+
+let data = [(1, 2, 'a'); (5, 3, 'b'); (4, 1, 'c'); (5, 0, 'd')];;
+let _ :: (_, _, x) :: _ = data;;
+x;;
+
+(*
+ recursive function
+ with pattern matching to find
+ length of list
+*)
+
+(**
+ * {length l} returns the number of elements
+ * in the list {l} - non tail recursive
+ *)
+let rec length l =
+ match l with
+ | [] -> 0
+ | x :: xs -> 1 + length xs;;
+
+(**
+ * {length_tr l} returns the number of elements
+ * in the list {l} - tail recursive
+ *)
+let length_tr l =
+ let rec aux acc l =
+ match l with
+ | [] -> acc
+ | _ :: xs -> aux (acc + 1) xs
+ in
+ aux 0 l;;
+
+(*
+ GENERATE WEB DOCUMENTATION
+
+ mkdir html
+ ocamldoc -html -d html main.ml
+
+*)
+
+(*
+ there is no void in ocaml,
+ everything has to return a value
+ all expressions have a value;
+
+ if your function has no value to
+ return, you still need to return something
+ so return the unit value
+
+ example:
+ printf is like a utility to print to the
+ console but does not need to return any value
+ so it returns the unit value
+*)
+Printf.printf "Hello, world\n";;
diff --git a/tinker/exponential.ml b/tinker/exponential.ml
deleted file mode 100644
index 99dd140..0000000
--- a/tinker/exponential.ml
+++ /dev/null
@@ -1,20 +0,0 @@
-let fact n =
- let rec fact' acc i =
- if i = 0. then acc
- else fact' (i *. acc) (i -. 1.)
- in
- fact' 1. n;;
-
-let pow a b =
- let rec pow' acc i =
- if i = 0. then acc
- else pow' (acc *. a) (i -. 1.)
- in
- pow' 1. b;;
-
-let expo n x =
- let rec expo' acc i =
- if i = 0. then acc
- else expo' (acc +. pow x i /. fact i) (i -. 1.)
- in
- expo' 1. n;;
diff --git a/tinker/tinker.ml b/tinker/tinker.ml
deleted file mode 100644
index e5bb181..0000000
--- a/tinker/tinker.ml
+++ /dev/null
@@ -1,18 +0,0 @@
-let pow b e =
- let rec pow' acc i =
- if i = 0 then acc
- else pow' (acc * b) (i - 1)
- in
- pow' 1 e;;
-
-let rec root n k g =
- let next = (1. /. k) *. ((k -. 1.) *. g +. n /. float_of_int (pow g (k - 1))) in
- if abs(next - g) < 0.00000000001 then next
- else root n k next;;
-
-let float_pow b e =
- let rec float_pow' acc i =
- if i <= 0. then acc
- else float_pow' (acc *. b) (i -. 1.)
- in
- float_pow' 1. e;;