I'm trying to make a function that, given a tuple list (I don't know if tuple is the correct term, what i mean is a (x,y) list) and an n-ary tree, it returns the leaf that you get from checking if a key in the tuple is present in the tree, and taking the child in the position of the value associated to that key, if it doesn't exist, raise an error.
I know I didn't explain it well, so I'll help myself with an example. tuple list = [(1,3);(2,2);(3,1);(10,1)] if the the root's value is 1 then it will check the third child (if not it will go on with the list), then if the child's value is 10, it will check his first child until it will find a leaf.
What i thought to do was to first use List.map to remove the elements that don't match with a tuple's key and the childs that are not in the associated value's value position, and then do the same to their childs recursively.
Here is what I did:
type 'a ntree = Tr of 'a * 'a ntree list;;
let leaf x = Tr(x,[]);;
let alb = Tr(1,[Tr(2,[leaf 3; leaf 4; leaf 2]);Tr(5,[leaf 11; leaf 10]);Tr(3,[leaf 9; leaf 7; leaf 10])]);;
let guida = [(1,3);(2,2);(3,1);(10,1);(16,2);(11,2)];;
let rec cerca_foglia guida (Tr(x,tlist)) =
match tlist with
[] -> x
|_ -> List.map(fun a -> List.mem_assoc x guida && (*a.position = List.nth tlist List.assoc x guida*)) (cerca tlist)
and cerca = function
[] -> raise NotFound
|[t] -> cerca_foglia guida t
|t::rest ->
try cerca_foglia guida t
with NotFound -> cerca rest
Of course, a.position does not exist, so how can I check it?
I also tried it differently:
let rec cerca_foglia guida (Tr(x,tlist)) =
match tlist with
[] -> x
|_ -> List.map(fun a -> a = List.nth tlist List.assoc x guida) (cerca tlist)
and cerca = function
[] -> raise NotFound
|[t] -> if List.mem_assoc t guida then cerca_foglia guida t else raise NotFound
|t::rest ->
try cerca_foglia guida t
with NotFound -> cerca rest
But it still gives errors...How can I solve it?
After much pondering, I think I might have understood some of this. I have written two functions:
find_childandfind_child2.The
find_childfunction stops at the first match it finds. So evaluatingfind_child alb guidayields:The
find_child2function does something similar, but it only stops if it finds a "leaf" or if it doesn't find any of the keys it's looking for in the current node.And refactoring
find_child2a bit to clean it up and handle theFailure "nth"exception that may occur:Sketching out what the recursion looks like when we evaluate
find_child3 alb guida:Is this the kind of thing you're looking for?