I am actually sitting over a hour on a problem and donĀ“t find a solution for it.
I have this data type:
type 'a tree = Empty | Node of 'a * 'a tree * 'a tree
And i have to find a function which converts a given tree in a ordered list. There is also no invariant like that the left child has to be less then the right. I already found a "normal" recursion solution but not a tail recursive solution. I already thought about to build a unordered list and sort it with List.sort, but this uses a merge sort which is not tail recursive. Maybe someone has a good advice.
Thank you!
If you want to traverse the tree in order and return a list, that means our function inorder must have the type 'a tree -> 'a list.
let rec inorder t =
match t with
| Empty -> []
| Node (v, l, r) -> List.append (inorder l) (v :: (inorder r)) (* ! *)
However List.append is in tail position, not inorder. Another problem is we have two calls to inorder. If we put inorder l in tail position, inorder r could not possibly be in tail position - and vice versa.
A neat way to work around this problem is continuation passing style. We take our function above and convert it into a helper function with an extra parameter for our continuation, return
(* convert to helper function, add an extra parameter *)
let rec loop t return =
match t with
| Empty -> ...
| Node (v, l, r) -> ...
The continuation represents "what to do next", so instead of sending values directly out of our function, we must hand them to the continuation instead. That means for the Empty case, we'll return [] - instead of simply []
let rec loop t return =
match t with
| Empty -> return []
| Node (v, l, r) -> ...
For the Node (v, l, r) case, now that we have an extra parameter we can write our own continuation that informs loop what to do next. So to construct our sorted list, we will need to loop l, then loop r (or vice versa), then we can append them. We'll write our program just like this.
let rec loop t return =
match t with
| Empty -> return []
| Node (v, l, r) ->
loop l ... (* build the left_result *)
loop r ... (* build the right_result *)
return (List.append left_result (v :: right_result))
In this next step, we'll fill in the actual lambda syntax for the continuations.
let rec loop t return =
match t with
| Empty -> return []
| Node (v, l, r) ->
loop l (fun left ->
loop r (fun right ->
return (List.append left (v :: right))))
Last, we define inorder which is a call to loop with the default continuation, identity.
let identity x =
x
let inorder t =
let rec loop t return =
match t with
| Empty -> return []
| Node (v, l, r) ->
loop r (fun right ->
loop l (fun left ->
return (List.append left (v :: right))))
in
loop t identity
As you can see loop r (fun right -> ...) is in tail position for the Node branch. loop l (fun left -> ...) is in tail position of the first continuation. And List.append ... is in tail position of the second continuation. Provided List.append is a tail-recursive procedure, inorder will not grow the stack.
Note using List.append could be a costly choice for big trees. Our function calls it once per Node. Can you think of a way to avoid it? This exercise is left for the reader.
Given any list in Erlang, e.g.:
L = [foo, bar, foo, buzz, foo].
How can I only show the unique items of that list, using a recursive function?
I do not want to use an built-in function, like one of the lists functions (if it exists).
In my example, where I want to get to would be a new list, such as
SL = [bar, buzz].
My guess is that I would first sort the list, using a quick sort function, before applying a filter?
Any suggestions would be helpful. The example is a variation of an exercise in chapter 3 of Cesarini's & Thompson's excellent "Erlang Programming" book.
I propose this one:
unique(L) ->
unique([],L).
unique(R,[]) -> R;
unique(R,[H|T]) ->
case member_remove(H,T,[],true) of
{false,Nt} -> unique(R,Nt);
{true,Nt} -> unique([H|R],Nt)
end.
member_remove(_,[],Res,Bool) -> {Bool,Res};
member_remove(H,[H|T],Res,_) -> member_remove(H,T,Res,false);
member_remove(H,[V|T],Res,Bool) -> member_remove(H,T,[V|Res],Bool).
The member_remove function returns in one pass the remaining tail without all occurrences of the element being checked for duplicate and the test result.
I may do it this way :)
get_unique(L) ->
SortedL = lists:sort(L),
get_unique(SortedL, []).
get_unique([H | T], [H | Acc]) ->
get_unique(T, [{dup, H} | Acc]);
get_unique([H | T], [{dup, H} | Acc]) ->
get_unique(T, [{dup, H} | Acc]);
get_unique([H | T], [{dup, _} | Acc]) ->
get_unique(T, [H | Acc]);
get_unique([H | T], Acc) ->
get_unique(T, [H | Acc]);
get_unique([], [{dup, _} | Acc]) ->
Acc;
get_unique([], Acc) ->
Acc.
I think idea might be: check if you already seen the head of list. If so, skip it and recursively check the tail. If not - add current head to results, to 'seen' and recursively check the tail. Most appropriate structure for checking if you already have seen the item is set.
So,i'd propose following:
remove_duplicates(L) -> remove_duplicates(L,[], sets:new()).
remove_duplicates([],Result,_) -> Result;
remove_duplicates([Head|Tail],Result, Seen) ->
case sets:is_element(Head,Seen) of
true -> remove_duplicates(Tail,Result,Seen);
false -> remove_duplicates(Tail,[Head|Result], sets:add_element(Head,Seen))
end.
Use two accumulators. One to keep elements you have seen so far, one to hold the actual result. If you see the item for the first time (not in Seen list) prepend the item to both lists and recurse. If you have seen the item before, remove it from your result list (Acc) before recursing.
-module(test).
-export([uniques/1]).
uniques(L) ->
uniques(L, [], []).
uniques([], _, Acc) ->
lists:reverse(Acc);
uniques([X | Rest], Seen, Acc) ->
case lists:member(X, Seen) of
true -> uniques(Rest, Seen, lists:delete(X, Acc));
false -> uniques(Rest, [X | Seen], [X | Acc])
end.
unique(List) ->
Set = sets:from_list(List),
sets:to_list(Set).
This solution only filters out duplicates from a list. probably requires building upon to make it do what you want.
remove_duplicates(List)->
lists:reverse(removing(List,[])).
removing([],This) -> This;
removing([A|Tail],Acc) ->
removing(delete_all(A,Tail),[A|Acc]).
delete_all(Item, [Item | Rest_of_list]) ->
delete_all(Item, Rest_of_list);
delete_all(Item, [Another_item| Rest_of_list]) ->
[Another_item | delete_all(Item, Rest_of_list)];
delete_all(_, []) -> [].
EDIT
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation. All rights reserved.
C:\Windows\System32>erl
Eshell V5.9 (abort with ^G)
1> List = [1,2,3,4,a,b,e,r,a,b,v,3,2,1,g,{red,green},d,2,5,6,1,4,6,5,{red,green}].
[1,2,3,4,a,b,e,r,a,b,v,3,2,1,g,
{red,green},
d,2,5,6,1,4,6,5,
{red,green}]
2> remove_duplicates(List).
[1,2,3,4,a,b,e,r,v,g,{red,green},d,5,6]
3>
Try the following code
-module(util).
-export([unique_list/1]).
unique_list([]) -> [];
unique_list(L) -> unique_list(L, []).
% Base Case
unique_list([], Acc) ->
lists:reverse(Acc);
% Recursive Part
unique_list([H|T], Acc) ->
case lists:any(fun(X) -> X == H end, T) of
true ->
unique_list(lists:delete(H,T), Acc);
false ->
unique_list(T, [H|Acc])
end.
unique(L) -> sets:to_list(sets:from_list(L)).
The simplest way would be to use a function with an "accumulator" that keeps track of what elements you already have.
So you'd write a function like
% unique_acc(Accumulator, List_to_take_from).
You can still have a clean function, by not exporting the accumulator version, and instead exporting its caller:
-module(uniqueness).
-export([unique/1]).
unique(List) ->
unique_acc([], List).
If the list to take from is empty, you're done:
unique_acc(Accumulator, []) ->
Accumulator;
And if it's not:
unique_acc(Accumulator, [X|Xs]) ->
case lists:member(X, Accumulator) of
true -> unique_acc(Accumulator, Xs);
false -> unique_acc([X|Accumulator], Xs)
end.
2 things to note:
-- This does use a list BIF -- lists:member/2. You can easily write this yourself, though.
-- The order of the elements are reversed, from original list to result. If you don't like this, you can define unique/1 as lists:reverse(unique_acc([], List)). Or even better, write a reverse function yourself! (It's easy).
let find_free_next heap start =
for i = start to ((Array.length heap)-1) do
match heap.(i) with
Hdr (Free (h), g) ->
i
done
How can i return the index of a loop as an integer once the match has been found?
If you want to stick to the imperative style, you can use an exception to exit the loop:
exception Found of int
let find_free_next heap start =
try
for i = start to Array.length heap - 1 do
match heap.(i) with
| Hdr (Free (h), g) -> raise (Found i)
| _ -> () (* If it is not what you are seeking *)
done;
raise Not_found
with
| Found n -> n
But generally, as ppl have already written, functional style is more preferred in OCaml:
let find_free_next heap start =
let len = Array.length heap in
let rec find i =
if i >= len then None
else
match heap.(i) with
| Hdr (Free h, g) -> Some i
| _ -> find (i+1)
in
find start
In this example, there is not much difference between the two versions, but use of exceptions for exiting loops/recursions must be used with caution; you can introduce control flow bugs pretty easily with them, and they are sometimes hard to debug.
BTW, you can use Array.unsafe_get heap i to speed up your array access since you can be sure that i is always in the valid range of the array the above examples. (Oh, we need start >= 0 check in addition, though.)
Asumu Takikawa is right, the for loop in OCaml doesn't return a result. In idiomatic OCaml, you should use recursion instead. Ideally there would be a standard function like List.find that works for arrays. There is a function BatArray.findi in OCaml Batteries Included that does what you seem to want.
Simpler, and more efficient (no allocation at all):
let rec find_free_next heap start =
if start = Array.length heap then raise Not_found;
match heap.(i) with
| Hdr (Free h, g) -> i
| _ -> find_free_start heap (i+1)
Or, in imperative style:
let exit = Exit
let find_free_next heap start =
let pos = ref (-1) in
try
for i = start to Array.length heap - 1 do
match heap.(i) with
| Hdr (Free h, g) -> pos := i; raise exit
| _ -> ()
done;
raise Not_found
with Exit -> !pos
(notice that raise exit does not allocate only because the exception if precomputed).
Loops in Ocaml are supposed to be imperative, so it shouldn't return a result (aside from unit). So if you try to return a non-unit result, the compiler will give a warning.
The reason that Ocaml doesn't let you return a result from a loop is because this isn't a very functional idiom. If you use a recursive function instead of a loop, it's easy to exit early and return a result (by returning the result instead of recurring). If you want to write idiomatic Ocaml, you probably want to use recursion in this case.