The goal of this mini-project is to index strings, arrays, lists, lazy lists, streams, imperative lists, and binary trees.
The solutions for each question may vary from very short to semi-long.
The goal of this section is to index a string with a function of type string -> int -> char option:
from left to right
The implementation should satisfy the following unit tests:
let test_string_index_left_to_right candidate =
let b0 = (candidate "0123" 0 = Some '0')
and b1 = (candidate "0123" 1 = Some '1')
and b2 = (candidate "0123" 2 = Some '2')
and b3 = (candidate "0123" 3 = Some '3')
and b4 = (candidate "0123" 4 = None)
and b5 = (candidate "0123" ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
So:
from right to left
The implementation should satisfy the following unit tests:
let test_string_index_right_to_left candidate =
let b0 = (candidate "3210" 0 = Some '0')
and b1 = (candidate "3210" 1 = Some '1')
and b2 = (candidate "3210" 2 = Some '2')
and b3 = (candidate "3210" 3 = Some '3')
and b4 = (candidate "3210" 4 = None)
and b5 = (candidate "3210" ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
So:
The goal of this section is to index an array with a function of type 'a array -> int -> 'a option:
from left to right
The implementation should satisfy the following unit tests:
let test_array_index_left_to_right_int candidate =
let b0 = (candidate [|0; 1; 2; 3|] 0 = Some 0)
and b1 = (candidate [|0; 1; 2; 3|] 1 = Some 1)
and b2 = (candidate [|0; 1; 2; 3|] 2 = Some 2)
and b3 = (candidate [|0; 1; 2; 3|] 3 = Some 3)
and b4 = (candidate [|0; 1; 2; 3|] 4 = None)
and b5 = (candidate [|0; 1; 2; 3|] ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
let test_array_index_left_to_right_char candidate =
let b0 = (candidate [|'a'; 'b'; 'c'; 'd'|] 0 = Some 'a')
and b1 = (candidate [|'a'; 'b'; 'c'; 'd'|] 1 = Some 'b')
and b2 = (candidate [|'a'; 'b'; 'c'; 'd'|] 2 = Some 'c')
and b3 = (candidate [|'a'; 'b'; 'c'; 'd'|] 3 = Some 'd')
and b4 = (candidate [|'a'; 'b'; 'c'; 'd'|] 4 = None)
and b5 = (candidate [|'a'; 'b'; 'c'; 'd'|] ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
So:
from right to left
The implementation should satisfy the following unit tests:
let test_array_index_right_to_left_int candidate =
let b0 = (candidate [|3; 2; 1; 0|] 0 = Some 0)
and b1 = (candidate [|3; 2; 1; 0|] 1 = Some 1)
and b2 = (candidate [|3; 2; 1; 0|] 2 = Some 2)
and b3 = (candidate [|3; 2; 1; 0|] 3 = Some 3)
and b4 = (candidate [|3; 2; 1; 0|] 4 = None)
and b5 = (candidate [|3; 2; 1; 0|] ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
let test_array_index_right_to_left_char candidate =
let b0 = (candidate [|'d'; 'c'; 'b'; 'a'|] 0 = Some 'a')
and b1 = (candidate [|'d'; 'c'; 'b'; 'a'|] 1 = Some 'b')
and b2 = (candidate [|'d'; 'c'; 'b'; 'a'|] 2 = Some 'c')
and b3 = (candidate [|'d'; 'c'; 'b'; 'a'|] 3 = Some 'd')
and b4 = (candidate [|'d'; 'c'; 'b'; 'a'|] 4 = None)
and b5 = (candidate [|'d'; 'c'; 'b'; 'a'|] ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
So:
The goal of this section is to index a list with a function of type 'a list -> int -> 'a option.
from left to right
The implementation should satisfy the following unit tests:
let test_list_index_left_to_right_int candidate =
let b0 = (candidate [0; 1; 2; 3] 0 = Some 0)
and b1 = (candidate [0; 1; 2; 3] 1 = Some 1)
and b2 = (candidate [0; 1; 2; 3] 2 = Some 2)
and b3 = (candidate [0; 1; 2; 3] 3 = Some 3)
and b4 = (candidate [0; 1; 2; 3] 4 = None)
and b5 = (candidate [0; 1; 2; 3] ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
let test_list_index_left_to_right_char candidate =
let b0 = (candidate ['a'; 'b'; 'c'; 'd'] 0 = Some 'a')
and b1 = (candidate ['a'; 'b'; 'c'; 'd'] 1 = Some 'b')
and b2 = (candidate ['a'; 'b'; 'c'; 'd'] 2 = Some 'c')
and b3 = (candidate ['a'; 'b'; 'c'; 'd'] 3 = Some 'd')
and b4 = (candidate ['a'; 'b'; 'c'; 'd'] 4 = None)
and b5 = (candidate ['a'; 'b'; 'c'; 'd'] ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
So:
from right to left
The implementation should satisfy the following unit tests:
let test_list_index_right_to_left_int candidate =
let b0 = (candidate [3; 2; 1; 0] 0 = Some 0)
and b1 = (candidate [3; 2; 1; 0] 1 = Some 1)
and b2 = (candidate [3; 2; 1; 0] 2 = Some 2)
and b3 = (candidate [3; 2; 1; 0] 3 = Some 3)
and b4 = (candidate [3; 2; 1; 0] 4 = None)
and b5 = (candidate [3; 2; 1; 0] ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
let test_list_index_right_to_left_char candidate =
let b0 = (candidate ['d'; 'c'; 'b'; 'a'] 0 = Some 'a')
and b1 = (candidate ['d'; 'c'; 'b'; 'a'] 1 = Some 'b')
and b2 = (candidate ['d'; 'c'; 'b'; 'a'] 2 = Some 'c')
and b3 = (candidate ['d'; 'c'; 'b'; 'a'] 3 = Some 'd')
and b4 = (candidate ['d'; 'c'; 'b'; 'a'] 4 = None)
and b5 = (candidate ['d'; 'c'; 'b'; 'a'] ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
So:
Subsidiary questions:
The goal of this section is to index a lazy list with a function of type 'a llist -> int -> 'a option, where the polymorphic type llist is defined as follows:
type 'a llist =
| Lnil
| Lcons of 'a * 'a llist Lazy.t;;
from left to right
The implementation should satisfy the following unit tests:
let test_llist_index_left_to_right_int candidate =
let b0 = (candidate (Lcons (0, lazy (Lcons (1, lazy (Lcons (2, lazy (Lcons (3, lazy Lnil)))))))) 0 = Some 0)
and b1 = (candidate (Lcons (0, lazy (Lcons (1, lazy (Lcons (2, lazy (Lcons (3, lazy Lnil)))))))) 1 = Some 1)
and b2 = (candidate (Lcons (0, lazy (Lcons (1, lazy (Lcons (2, lazy (Lcons (3, lazy Lnil)))))))) 2 = Some 2)
and b3 = (candidate (Lcons (0, lazy (Lcons (1, lazy (Lcons (2, lazy (Lcons (3, lazy Lnil)))))))) 3 = Some 3)
and b4 = (candidate (Lcons (0, lazy (Lcons (1, lazy (Lcons (2, lazy (Lcons (3, lazy Lnil)))))))) 4 = None)
and b5 = (candidate (Lcons (0, lazy (Lcons (1, lazy (Lcons (2, lazy (Lcons (3, lazy Lnil)))))))) ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
let test_llist_index_left_to_right_char candidate =
let b0 = (candidate (Lcons ('a', lazy (Lcons ('b', lazy (Lcons ('c', lazy (Lcons ('d', lazy Lnil)))))))) 0 = Some 'a')
and b1 = (candidate (Lcons ('a', lazy (Lcons ('b', lazy (Lcons ('c', lazy (Lcons ('d', lazy Lnil)))))))) 1 = Some 'b')
and b2 = (candidate (Lcons ('a', lazy (Lcons ('b', lazy (Lcons ('c', lazy (Lcons ('d', lazy Lnil)))))))) 2 = Some 'c')
and b3 = (candidate (Lcons ('a', lazy (Lcons ('b', lazy (Lcons ('c', lazy (Lcons ('d', lazy Lnil)))))))) 3 = Some 'd')
and b4 = (candidate (Lcons ('a', lazy (Lcons ('b', lazy (Lcons ('c', lazy (Lcons ('d', lazy Lnil)))))))) 4 = None)
and b5 = (candidate (Lcons ('a', lazy (Lcons ('b', lazy (Lcons ('c', lazy (Lcons ('d', lazy Lnil)))))))) ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
So:
from right to left
The implementation should satisfy the following unit tests:
let test_llist_index_right_to_left_int candidate =
let b0 = (candidate (Lcons (3, lazy (Lcons (2, lazy (Lcons (1, lazy (Lcons (0, lazy Lnil)))))))) 0 = Some 0)
and b1 = (candidate (Lcons (3, lazy (Lcons (2, lazy (Lcons (1, lazy (Lcons (0, lazy Lnil)))))))) 1 = Some 1)
and b2 = (candidate (Lcons (3, lazy (Lcons (2, lazy (Lcons (1, lazy (Lcons (0, lazy Lnil)))))))) 2 = Some 2)
and b3 = (candidate (Lcons (3, lazy (Lcons (2, lazy (Lcons (1, lazy (Lcons (0, lazy Lnil)))))))) 3 = Some 3)
and b4 = (candidate (Lcons (3, lazy (Lcons (2, lazy (Lcons (1, lazy (Lcons (0, lazy Lnil)))))))) 4 = None)
and b5 = (candidate (Lcons (3, lazy (Lcons (2, lazy (Lcons (1, lazy (Lcons (0, lazy Lnil)))))))) ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
let test_llist_index_right_to_left_char candidate =
let b0 = (candidate (Lcons ('d', lazy (Lcons ('c', lazy (Lcons ('b', lazy (Lcons ('a', lazy Lnil)))))))) 0 = Some 'a')
and b1 = (candidate (Lcons ('d', lazy (Lcons ('c', lazy (Lcons ('b', lazy (Lcons ('a', lazy Lnil)))))))) 1 = Some 'b')
and b2 = (candidate (Lcons ('d', lazy (Lcons ('c', lazy (Lcons ('b', lazy (Lcons ('a', lazy Lnil)))))))) 2 = Some 'c')
and b3 = (candidate (Lcons ('d', lazy (Lcons ('c', lazy (Lcons ('b', lazy (Lcons ('a', lazy Lnil)))))))) 3 = Some 'd')
and b4 = (candidate (Lcons ('d', lazy (Lcons ('c', lazy (Lcons ('b', lazy (Lcons ('a', lazy Lnil)))))))) 4 = None)
and b5 = (candidate (Lcons ('d', lazy (Lcons ('c', lazy (Lcons ('b', lazy (Lcons ('a', lazy Lnil)))))))) ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
So:
The goal of this section is to index a stream with a function of type 'a stream -> int -> 'a option, where the polymorphic type stream is defined as follows:
type 'a stream =
| Scons of 'a * 'a stream Lazy.t;;
The goal of this section is to index a list with a function of type 'a ilist -> int -> 'a option.
from left to right
The implementation should satisfy the following unit tests:
let test_ilist_index_left_to_right_int candidate =
let b0 = (candidate (Icons (0, ref (Icons (1, ref (Icons (2, ref (Icons (3, ref Inil)))))))) 0 = Some 0)
and b1 = (candidate (Icons (0, ref (Icons (1, ref (Icons (2, ref (Icons (3, ref Inil)))))))) 1 = Some 1)
and b2 = (candidate (Icons (0, ref (Icons (1, ref (Icons (2, ref (Icons (3, ref Inil)))))))) 2 = Some 2)
and b3 = (candidate (Icons (0, ref (Icons (1, ref (Icons (2, ref (Icons (3, ref Inil)))))))) 3 = Some 3)
and b4 = (candidate (Icons (0, ref (Icons (1, ref (Icons (2, ref (Icons (3, ref Inil)))))))) 4 = None)
and b5 = (candidate (Icons (0, ref (Icons (1, ref (Icons (2, ref (Icons (3, ref Inil)))))))) ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
let test_ilist_index_left_to_right_char candidate =
let b0 = (candidate (Icons ('a', ref (Icons ('b', ref (Icons ('c', ref (Icons ('d', ref Inil)))))))) 0 = Some 'a')
and b1 = (candidate (Icons ('a', ref (Icons ('b', ref (Icons ('c', ref (Icons ('d', ref Inil)))))))) 1 = Some 'b')
and b2 = (candidate (Icons ('a', ref (Icons ('b', ref (Icons ('c', ref (Icons ('d', ref Inil)))))))) 2 = Some 'c')
and b3 = (candidate (Icons ('a', ref (Icons ('b', ref (Icons ('c', ref (Icons ('d', ref Inil)))))))) 3 = Some 'd')
and b4 = (candidate (Icons ('a', ref (Icons ('b', ref (Icons ('c', ref (Icons ('d', ref Inil)))))))) 4 = None)
and b5 = (candidate (Icons ('a', ref (Icons ('b', ref (Icons ('c', ref (Icons ('d', ref Inil)))))))) ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
So:
from right to left
The implementation should satisfy the following unit tests:
let test_ilist_index_right_to_left_int candidate =
let b0 = (candidate (Icons (3, ref (Icons (2, ref (Icons (1, ref (Icons (0, ref Inil)))))))) 0 = Some 0)
and b1 = (candidate (Icons (3, ref (Icons (2, ref (Icons (1, ref (Icons (0, ref Inil)))))))) 1 = Some 1)
and b2 = (candidate (Icons (3, ref (Icons (2, ref (Icons (1, ref (Icons (0, ref Inil)))))))) 2 = Some 2)
and b3 = (candidate (Icons (3, ref (Icons (2, ref (Icons (1, ref (Icons (0, ref Inil)))))))) 3 = Some 3)
and b4 = (candidate (Icons (3, ref (Icons (2, ref (Icons (1, ref (Icons (0, ref Inil)))))))) 4 = None)
and b5 = (candidate (Icons (3, ref (Icons (2, ref (Icons (1, ref (Icons (0, ref Inil)))))))) ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
let test_ilist_index_right_to_left_char candidate =
let b0 = (candidate (Icons ('d', ref (Icons ('c', ref (Icons ('b', ref (Icons ('a', ref Inil)))))))) 0 = Some 'a')
and b1 = (candidate (Icons ('d', ref (Icons ('c', ref (Icons ('b', ref (Icons ('a', ref Inil)))))))) 1 = Some 'b')
and b2 = (candidate (Icons ('d', ref (Icons ('c', ref (Icons ('b', ref (Icons ('a', ref Inil)))))))) 2 = Some 'c')
and b3 = (candidate (Icons ('d', ref (Icons ('c', ref (Icons ('b', ref (Icons ('a', ref Inil)))))))) 3 = Some 'd')
and b4 = (candidate (Icons ('d', ref (Icons ('c', ref (Icons ('b', ref (Icons ('a', ref Inil)))))))) 4 = None)
and b5 = (candidate (Icons ('d', ref (Icons ('c', ref (Icons ('b', ref (Icons ('a', ref Inil)))))))) ~-1 = None)
in b0 && b1 && b2 && b3 && b4 && b5;;
Subsidiary question:
This mini-project builds on the mini-project about depth-first and breadth-first traversals. Its goal is to index a binary tree with a function of type 'a binary_tree -> int -> 'a option, where the polymorphic type binary_tree is defined as follows:
type 'a binary_tree =
| Leaf of 'a
| Node of 'a binary_tree * 'a binary_tree;;
The tree traversals should be:
Since
is it possible to “reverse” a binary tree so that indexing this reversed tree from left to right is equivalent to indexing this tree from right to left? If so, what is this “reverse” transformation?
Created [10 Jan 2023]