I am trying to implement a function treeToString that uses this data type:
datatype Tree = LEAF of string | NODE of Tree list;
and this tree:
val L1a = LEAF "a"
val L1b = LEAF "b"
val L1c = LEAF "c"
val L2a = NODE [L1a, L1b, L1c]
val L2b = NODE [L1b, L1c, L1a]
val L3 = NODE [L2a, L2b, L1a, L1b]
val L4 = NODE [L1c, L1b, L3]
val L5 = NODE [L4]
The function takes an argument like treeToString L5 which will output the string ((cb((abc)(bca)ab)))
The problem is I cannot figure out the correct way to differentiate between when the function takes in a LEAF or a NODE type. I wrote the code below to try and test this but I am getting errors. Anyone know the syntax in order to get this to work? Once I get the parameters down, the actual recursion should be easy.
(* treeToString *)
fun treeToString(LEAF str) = str
| treeToString(NODE h::t) =
h;
This function is what I used to get it working. Just needed to add parenthesis around my arguments
fun treeToString f Node = let
fun helperFun (LEAF(v)) = [f v]
| helperFun (NODE(h::t)) = ["("] # List.concat (map helperFun(h::t)) # [")"]
in
String.concat(helperFun Node)
end;
Change this:
| treeToString(NODE h::t) = ...
To this:
| treeToString (NODE (h::t)) = ...
The reason is that (NODE h::t) can be interpreted as either ((NODE h)::t) (where NODE h is the first item in a list of NODE's) or as (NODE (h::t)), which is what you want.
Related
I'm just a begginer in Ocaml, and I wanted to study the graph theory, but with implementations in Ocaml. And I've got a trouble to do something : I just wanted to list the connected components of a graph by using a Depth first search. So, I did :
#open "stack" ;;
let non_empty pile =
try push (pop pile) pile ; true with Empty -> false ;;
let connected_comp g =
let already_seen = make_vect (vect_length g) false in
let comp = [] in
let dfs s lst =
let totreat = new () in
already_seen.(s) <- true; push s totreat;
let rec add_neighbour l = match l with
| [] -> ()
| q::r when already_seen.(q) = false -> push q totreat; already_seen.(q) <- true; add_neighbour r
| q::r -> add_neighbour r
in
while non_empty totreat do
let s = pop totreat in
already_seen.(s) <- true;
(* we want to add s to the list lst *) s::lst;
add_neighbour g.(s);
done
in
let rec head_list l = match l with
| [] -> failwith "Empty list"
| p::q -> p
in
let rec aux comp t = match t with
| t when t = vect_length g -> comp
| t when already_seen.(t) = true -> aux comp (t+1)
| t -> aux ((dfs t [])::comp) (t+1) (* we want that dfs t [] return the list lst modified *)
in aux comp 0;;
And I obtain :
> | t -> (dfs t [])::comp ; aux comp (t+1) (* we want that dfs t [] return the list lst modified *)
> ^^^^^^^^^^^^^^^^
Warning : this expression is of type unit list,
but is used with the type unit.
connected_comp : int list vect -> unit list = <fun>
- : unit list = []
- : unit = ()
Of course, I'm not surprised. But what I want to do is that the function dfs return the list sent on argument (the lst list) but modified, and here it's not the case as the function is of type unit, cause it return nothing. But in Ocaml, as the language is made for returning the last expression I think, I don't know how to do. I could as well use recursive algorithm for the dfs function, as, through filtering, it would permit me to return the list, but I just wanted to learn about Ocaml, and so modified (even if it's not optimal) my algorithm.
Someone could help me, please ?
Edit : As we ask me, I will try to reduce my code and get to the point. So, I have the function dfs which correspond to a Depth first search (for a graph)
let dfs s lst =
let totreat = new () in
already_seen.(s) <- true; push s totreat;
let rec add_neighbour l = match l with
| [] -> ()
| q::r when already_seen.(q) = false -> push q totreat; already_seen.(q) <- true; add_neighbour r
| q::r -> add_neighbour r
in
while non_empty totreat do
let s = pop totreat in
already_seen.(s) <- true;
(* we want to add s to the list lst *) s::lst;
add_neighbour g.(s);
done
in
(alreadyseen is a vector of boolean, defined previously)
And my only problem is that I want that the function return the list lst modified (in the loop while), when, at this point, it's a unit function.
I tried to define lst as a reference, but then I don't know how to return it...
I hope it's more clear, I'm not familiar with all of this at the moment...
Thank you !
Here is a degraded version of your code that demonstrate one way to do what you want.
let non_empty _ = false
let dfs s lst =
let local_lst = ref lst in
while non_empty () do
(*do stuff here*)
let s = 1 in
local_lst := s::!local_lst;
(*do stuff here*)
done;
!local_lst
I first initialize a local mutable value local_lst to the list lst given as an argument. I then update this value in the while loop. And finally I return the value stored in local_lst.
I have a following function that defines a treeļ¼
datatype 'a tree = leaf of 'a |
node of 'a tree * 'a tree;
fun cat(leaf(s)) = s
| cat(node(t1,t2)) = cat(t1) ^ " " ^ cat(t2);
The cat function is used to concatenates strings input to the string tree.
I know it is not tail recursive since the definition use the function itself for recursion.
Now I am thinking if there is any way to make it in the ways of tail recursive?
Thanks in advance for any helps.
Here would be the tail recursive version
fun cat'(leaf(s), acc) = s^acc
| cat'(node(t1, node(t2, acc))
You can also do it as a continuation passing style function
fun cat'' (leaf(s)) k = k(s)
| cat'' (node(t1, t2)) k = cat''(t1) (fn res => k(res ^ cat''(t2)))
Hope this helps!! :D
I don't have any idea on how to change the code for my add function.
type trie = Node of bool * (char * trie) list
let explode word =
let rec explode' i acc =
if i < 0 then acc else explode' (i-1) (word.[i] :: acc)
in explode' (String.length word - 1) []
let rec exists w tr = match w, tr with
| [], Node (b, _) -> b
| h::t, Node (_, l) -> try exists t (List.assoc h l) with Not_found -> false
let rec add w tr = match w, tr with
| [], Node (_, l) -> Node (true, l)
| h :: t, Node (b, l) -> try add t (List.assoc h l)
with Not_found -> Node (false, (h, add t tr) :: l)
The problem is when List.assoc h l finds something , then I don't keep track of my structure, no Node is built during the recursive call so I am losing data.
Example :
# let empty = Node(true, []);;
- : trie = Node (true, [])
# let w = explode "hi";;
val w : char list = ['h'; 'i']
# let ww = explode "hit";;
val ww : char list = ['h'; 'i'; 't']
# let tr = add w x;;
val tr : trie = Node (false, [('h', Node (false, [('i', Node (true, []))]))])
# add ww tr;;
- : trie = Node (false, [('t', Node (true, []))])
It seems your basic plan is to work down through the data structure with List.assoc, then add your new node when you find the right spot. This makes sense if you can modify the structure. However, your data structure is immutable. With immutable data, your basic plan must be to build a new data structure rather than to modify the old one. So you have to imagine yourself finding the right spot while keeping traack of the old structure along the way, then building up a new structure starting from the spot.
Here's some code that keeps an association list counting the number of instances of characters seen so far. Note that it returns a new association list rather than modifying the old one (which is impossible):
let rec add_char_count list char =
match list with
| [] -> [(char, 1)]
| (hchar, hcount) :: t ->
if hchar = char then (hchar, hcount + 1) :: t
else (hchar, hcount) :: add_char_count t char
The recursive call (hchar, hcount) :: add_char_count t char is the spot where the old structure is remembered. It rebuilds the old structure from the part of the list before where the new character is added.
I need to write an algorithm called reverseNodes that takes a RefToNode as a parameter and recuriveley reverses the list the header i came up with was
Algorithm reverse (rList)
reverves elementsin a list
Pre: rList :: a referance to a list to be reversed
Post: elements in rList are reversed
if ( rList !=NULL)
reverseNodes (rList -> head)
return
I need to find a way to write this is psuedocode and find the time complexity
Sometimes it is easier to create some un-formal algorithm gibberish, if you start
with the idea expressed clearly. Then, obfuscate and verbalize until you have something, your professor will happily accept.
So, lets start with our general idea of the algorithm:
let rec fold folder acc l =
match l with
| [] -> acc
| x::xs -> fold folder (folder acc x) xs
let prepend l e = e :: l
let revlist l = fold prepend [] l
...and start to verbalize:
let result = empty list
let l = the list we want to reverse
if l is the empty list, goto 7
let head = l.front, l = l.pop_front()
result.push_front head
goto 3
l = result
The steps 3..6 can be easily expressed as a recursive function:
void loop(list& l, list& result)
{
if( l.is_empty()) return;
auto head = l.front();
l.pop_front();
result.push_front(head);
loop(l,result);
}
As we want to create the illusion of in-place.reversal, our reverse_list function is
void reverse_list( list& l )
{
list result;
loop( l, result);
l = result;
}
Alternate solution
We can also do it in another way:
let rec revlist1 l =
match l with
| [] -> l
| x::xs -> (revlist1 xs) # [x]
This basically states, that the reversed list is the front element of the original list appended to the reverse of the rest.
Translating the algorithm to gibberish form yields:
Node* reverse_list1( Node* list )
{
if( list == NULL) return NULL; // reverse of empty list is empty list.
if( list->next == NULL ) // last element in list?
return list; // the reverse of a list with 1 element is the same.
else
{
Node* head = list;
Node* tail = list->next;
head->next = NULL;
Node* end_of_reverse_tail = tail; // the first will be the last...
Node * result = reverse_list1(tail);
end_of_reverse_tail->next = head;
return result;
}
}
Note, that this is not a tail recursive solution.
It is easy enough to write recursive inorder traversal in OCaml, but how to write iterative one? with for loop or while?
Asking for someone to write something without recursive calls is stupid, but I'll still do it because it's an interesting exercise. Going from recursive to iterative is always the same process.
type tree = Leaf | Node of int * tree * tree
let rec in_order = function
| Leaf -> []
| Node(i,l,r) -> in_order l # (i :: in_order r);;
Alright, now we have our recursive function. The first step is to transform it to tail recursive. This is actually the hardest step since it requires a real logical and algorithmic change.
We are going to add a new parameter to the function that is going to contain the result of the computation :
let rec ino res = function
| Leaf -> ()
| Node(i,l,r) ->
begin
ino res r ;
res := i :: !res ;
ino res l
end
At the end, the result is !res.
Now that we have this, removing the recursive call is very easy, we just have to think about what does the compiler does when he has a recursive call. Well, it just does a while loop, after putting the parameters of the function and the next work to do in a stack. Let's just do it.
open Stack
type work = Value of int | NextNode of tree ref
let ino t : int list =
let res = ref [] in
let stack = Stack.create () in
push (NextNode (ref t)) stack;
try
while true do
let current = pop stack in
match current with
Value i -> res := i :: !res
| NextNode n ->
begin
match !n with
Leaf -> ()
| Node(i,l,r) ->
begin
push (NextNode (ref l)) stack;
push (Value i) stack;
push (NextNode (ref r)) stack
end
end
done;
assert false
with
| Empty -> !res
Here we just remember the next thing to do. We know that when we reach a node we have to treat its right child, then the value of the node, then its left child, so we just put all this in the stack (in reverse order of course), and we keep going to the next element of the stack. When the stack is empty, we have visited the whole tree, and we can return.
I hope that this post manages to convince some people of the power of recursion over iterative programming. 3 lines Vs 26 lines. QED.
Here's another take on iterative in-order traversals:
type 'a node = {mutable data: 'a;
mutable left : 'a node option;
mutable right: 'a node option; }
let new_node data = {data; left = None; right = None;}
let insert tree new_data =
let module Wrapper = struct exception Stop_loop end in
let iter = ref tree in
try
while true do
if new_data < !iter.data
then match !iter.left with
| None ->
!iter.left <- Some (new_node new_data);
raise Wrapper.Stop_loop
| Some left_tree -> iter := left_tree
else if new_data > !iter.data
then match !iter.right with
| None ->
!iter.right <- Some (new_node new_data);
raise Wrapper.Stop_loop
| Some right_tree -> iter := right_tree
done
with Wrapper.Stop_loop -> ()
let in_order_traversal tree =
let module W = struct exception Stop_loop end in
let visited_stack = Stack.create () in
let iter_node = ref (Some tree) in
try while true do
(* Inner loop, we keep trying to go left *)
(try while true do
match !iter_node with
| None -> raise W.Stop_loop
| Some left ->
Stack.push left visited_stack;
iter_node := left.left
done;
with W.Stop_loop -> ());
(* If we have no more to process in the stack, then we're
done *)
if Stack.length visited_stack = 0
then raise W.Stop_loop
else
(* Here we're forced to start moving rightward *)
let temp = Stack.pop visited_stack in
Printf.sprintf "%s " temp.data |> print_string;
iter_node := temp.right
done
with W.Stop_loop -> ()
let () =
let root = new_node "F" in
["B";"G";"A";"D";"I";"C";"E";"H"] |> List.iter (insert root);
in_order_traversal root;
print_newline ();