Files
comp3958/lecture02/lists.ml
T
2026-01-15 15:03:48 -08:00

188 lines
4.9 KiB
OCaml

(*
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 *)