Here's a type for binary trees
type tree =
| Node of tree * int * tree
| Null;;
and I've got a following problem to solve:
Write a function tree -> tree -> int that returns a number which says for how many levels down (going from the root) the trees are essentialy the same (same values at nodes and same shapes). Here's a solution I wrote:
let rec identical l1 l2 =
match (l1, l2) with
| ([], []) -> true
| ((tree1, s1) :: t1, (tree2, s2) :: t2) ->
if s1 = s2 then
match (tree1, tree2) with
| (Null, Null) -> identical t1 t2
| (_, Null) -> false
| (Null, _) -> false
| (Node (l1, x1, r1), Node (l2, x2, r2)) ->
if x1 = x2 then identical t1 t2
else false
else false;;
let unfold l =
let l = List.filter (fun (a, b) ->
if a = Null then false else true) l in
if List.length l = 0 then raise Nulls else
List.fold_left (fun acc (a, b) ->
match a with
| Node (l, x, r) ->
(l, "l") :: (r, "r") :: acc) [] l;;
let compare t1 t2 =
let rec aux l1 l2 result =
if (List.length l1 <> List.length l2)
then result
else
if (identical l1 l2) then
try
aux (unfold l1) (unfold l2) (result + 1)
with
| Nulls -> result
else
result
in aux [(t1, "r")] [(t2, "r")] 0;;
The problem is I'm really dissatisfied with this code - it's really hard to understand, even for me. What I'm doing is essentially on every level of the tree I'm creating a list for left and right tree containing all subtrees on corresponding levels (and also whether the subtree is left or right son for determining the shape) and then comparing this list on every level. If they are identical I increment the result, if not - I return the result.
But when I use this "algorithm" I end up with this complicated code. So could it be done simplier?