#include "BUCASCS320.hats"
datatype bintree =
| E of ()
| B of (bintree, int, bintree)
fun bintree_size (t: bintree): int =
case+ t of
| B (t1, _, t2) => 1 + bintree_size t1 + bintree_size t2
| E () => 0
fun bintree_height (t: bintree): int =
case+ t of
| B (t1, _, t2) => 1 + max (bintree_height t1, bintree_height t2)
| E () => 0
fun bst_search (t: bintree, k0: int): bool =
case+ t of
| B (t1, k, t2) =>
if k0 < k then bst_search (t1, k0)
else if k0 > k then bst_search (t2, k0)
else true | E () => false
fun bst_insert (t: bintree, k0: int): bintree =
case+ t of
| B (t1, k, t2) => begin
if k0 <= k then B (bst_insert (t1, k0), k, t2)
else B (t1, k, bst_insert (t2, k0))
end | E () => B (E (), k0, E ())
fun bst_insertRT (t: bintree, k0: int): bintree =
case+ t of
| B (t1, k, t2) when k0 <= k => let
val t1_new = bst_insertRT (t1, k0)
val- B (t11_new, k0, t12_new) = t1_new
in
B (t11_new, k0, B (t12_new, k, t2))
end | B (t1, k, t2) => let
val t2_new = bst_insertRT (t2, k0)
val- B (t21_new, k0, t22_new) = t2_new
in
B (B (t1, k, t21_new), k0, t22_new)
end | E () => B (E (), k0, E ())
datatype tree (a:t@ype) =
| Lf(a) of ()
| Br(a) of (a, tree a, tree a)
exception Subscript of ()
fun{a:t@ype} subscript (t: tree a, k: int): a =
case+ t of
| Br (v, t1, t2) =>
if k = 1 then v
else if k mod 2 = 0
then subscript (t1, k / 2)
else subscript (t2, k / 2)
| Lf () => $raise Subscript ()
fun{a:t@ype}
update (t: tree a, k: int, w: a): tree a =
case+ t of
| Br (v, t1, t2) =>
if k = 1 then Br (w, t1, t2)
else if k mod 2 = 0
then Br (v, update (t1, k / 2, w), t2)
else Br (v, t1, update (t2, k / 2, w))
| Lf () => $raise Subscript ()
fun{a:t@ype} brauntree_size (t: tree a): int =
case+ t of
| Br (_, t1, t2) => 1 + brauntree_size (t1) + brauntree_size (t2)
| Lf () => 0