I have this code
type Tree<'T when 'T: comparison> =
| Empty
| Node of 'T * Tree<'T> * Tree<'T>
let rec insert value = function
| Empty -> Node(value, Empty, Empty)
| Node(v, left, right) when value < v -> Node(v, insert value left, right)
| Node(v, left, right) when value > v -> Node(v, left, insert value right)
| Node(_, _, _) as n -> n
but insteed of adding one integer I want to add a whole list of integers. Example:
let tree = addList [5;2;1;6;7];;
and the list should be added to the tree
You can simply do a fold like this
let tree = List.fold (fun tree x -> insert x tree) Empty [5;2;1;6;7];;
At each step you return a new tree, to which you add the next element during the next step. Instead of Empty you can use any existing tree to which you want to add the list of elements.
Related
I have a Tree type:
type Tree<'value> =
| Node of value: 'value * children: ConsList<Tree<'value>>
| Leaf of value: 'value
And a fold function for it:
let rec fold folder acc tree =
let f = fold folder
match tree with
| Leaf value -> folder acc value
| Node(value, children) -> ConsList.fold f (folder acc value) children
ConsList in case you need it:
type ConsList<'value> =
| Cons of head: 'value * tail: ConsList<'value>
| Empty
let rec fold folder acc lst =
let f = fold folder
match lst with
| Empty -> acc
| Cons (hd, tl) -> f (folder acc hd) tl
I need a foldBack function, meaning the function passes through the nodes from left to right from top to bottom, starting from the root.
I ended up on this:
let rec foldBack folder acc tree =
let f = fold folder
match tree with
| Leaf value -> f acc value
| Node(value, children) -> f value (f acc *children*)
Children with ** type is expected to be Tree<'a> but has type ConsList<Tree<Tree<'a>>>
For back folds it is common to have accumulator as a function which receives intermediate folded value of sub-branch and returns new folded value with respect to the current element. Thus iterating through the tree normally from top to bottom you literally construct the computation which when receives the terminal elements will compute the bottom to top fold.
You can look for continuation passing style topic more yourself. This approach is also used to optimize for tail-call recursion because function you accumulating is the chain of function objects which doesn't affect stack.
Here is what I've done so far (I replaced ConsList with normal List type, because otherwise it would require to create the foldBack for it as well, which you can try yourself)
type ConsList<'t> = 't list
type Tree<'value> =
| Node of value: 'value * children: ConsList<Tree<'value>>
| Leaf of value: 'value
let foldBack seed folder (tree: 't Tree) =
let rec fold acc tree =
match tree with
| Leaf value ->
let acc' inner = folder (acc inner) value
acc'
| Node (value, children) ->
let acc' inner = List.foldBack (fold acc) children inner
let acc'' inner = folder (acc' inner) value
acc''
fold id tree seed
let treeSample =
Node ("node1", [
Leaf "subnode1";
Node ("node1.1", [
Leaf "subnode1.1";
Node("node1.2", [
Leaf "leaf1.2"
])
])
])
treeSample|>foldBack ">>seed<<" (fun value acc -> $"{value} -> {acc}" )
val it: string = ">>seed<< -> leaf1.2 -> node1.2 -> subnode1.1 -> node1.1 -> subnode1 -> node1"
I have type called type x and it has following members in the form of discriminated union
type Info= Empty | Value of int | Pair of (int * int)
I have a function which takes two arguments and filter the list according to comparisons made by n. I cannot figure out the last part. How can I compare each value of Pair with my n value in that function?
let filterInfo (n:int) (xs:Info list) = xs |> List.filter (fun (x) -> x <> Empty && x > Value n && // )
You can create a function that compares a single Info object by using pattern matching. Something like this should suffice:
let compareInfo (n:int) (info:Info) =
match info with
| Empty -> false
| Value x -> n > x
| Pair (a, b) -> ...
You can call it by curring n from your filter call:
let filterInfo (n:int) (xs:Info list) = xs |> List.filter (compareInfo n)
I ended up adding a read-only property that pattern-matches on this:
type Thing =
| Sphere of Sphere * Surface
| Plane of Plane * Surface
member this.surface =
match this with
| Sphere(_, surface) -> surface
| Plane(_, surface) -> surface
How do you write a recursive function to build a binary tree where leafs are (value,index) with index a unique successive integer?
Current code is something like:
let rec MakeTree size =
if size = 0 then 0 else
match ran.Next (3) with
| 0 -> Cow (MakeTree (size-1),MakeTree (size-1))
| 1 -> Dog (MakeTree (size-1),MakeTree (size-1))
| 2 -> Cat (MakeTree (size-1),MakeTree (size-1))
Here are a version without values, but they are easy to add:
Define the tree like:
type Tree<'T when 'T: comparison> =
| Empty
| Node of 'T * Tree<'T> * Tree<'T>
And make a insert function like
let rec insert index = function
| Empty -> Node(index, Empty, Empty)
| Node(i, left, right) when index < i -> Node(i, insert index left, right)
| Node(i, left, right) when index > i -> Node(i, left, insert index right)
| Node(i, left, right) when index = i -> Node(index, left, right)
| Node(_, _, _) as n -> n
I have a list :
[objA;objB;objC;objD]
I need to do the following reduction :
obj -> obj -> obj
ie :
objA objB -> objB'
and then take back the original list so that I get :
[objB';objC;objD]
I am trying to do the following :
let rec resolveConflicts = function
| [] -> []
| [c] -> resolveConflict c
| [x;y] -> resolveConflict x
|> List.filter getMovesRelatedtoY
|> List.append y
|> resolveConflict
| [x;y::tail] ->
let y' = resolveConflict x
|> List.filter getMovesRelatedtoY
|> List.append y
resolveConflicts y'::tail
This syntax is not correct, may be I am not even using the correct tool... I am open to any well suited solution so that I can learn.
As to why, I filter the list and append one to another, it is just that every conflict is a list of moves.
To match first element, second element and the rest of the list, use this pattern:
| fst::snd::rest ->
You can match any constant number of first elements using this styling:
| fst::snd::thrd:: ... ::rest ->
this code i got is from Alexander Battisti about how to make a tree from a list of data:
let data = [4;3;8;7;10;1;9;6;5;0;2]
type Tree<'a> =
| Node of Tree<'a> * 'a * Tree<'a>
| Leaf
let rec insert tree element =
match element,tree with
| x,Leaf -> Node(Leaf,x,Leaf)
| x,Node(l,y,r) when x <= y -> Node((insert l x),y,r)
| x,Node(l,y,r) when x > y -> Node(l,y,(insert r x))
| _ -> Leaf
let makeTree = List.fold insert Leaf data
then i want to implement this code to my binary search tree code
let rec BinarySearch tree element =
match element,tree with
| x,Leaf -> BinarySearch (Node(Leaf,x,Leaf)) x
| x,Node(l,y,r) when x<=y ->
BinarySearch l y
| x,Node(l,y,r) when x>y ->
BinarySearch r y
| x,Node(l,y,r) when x=y ->
true
| _ -> false
then i use my search code like this:
> BinarySearch makeTree 5;;
and the result is none because it's like i got an infinite looping
can someone help me? if my code is wrong, please help me to correct it, thank you
The solution by Yin is how I would write it too.
Anyway, here is a solution that is closer to your version and (hopefully) explains what went wrong:
let rec BinarySearch tree element =
match element,tree with
| x, Leaf ->
// You originally called 'BinarySearch' here, but that's wrong - if we reach
// the leaf of the tree (on the path from root to leaf) then we know that the
// element is not in the tree so we return false
false
| x, Node(l,y,r) when x<y ->// This needs to be 'x<y', otherwise the clause would be
// matched when 'x=y' and we wouldn't find the element!
BinarySearch l element // Your recursive call was 'BinarySearch l y' but
// that's wrong - you want to search for 'element'
| x, Node(l,y,r) when x>y ->
BinarySearch r element
| x,Node(l,y,r) -> // You can simplify the code by omitting the 'when'
true // clause (because this will only be reached when
// x=y. Then you can omit the last (unreachable) case
let rec BinarySearch tree element =
match tree with
| Leaf -> false
| Node(l, v, r) ->
if v = element then
true
elif v < element then
BinarySearch r element
else
BinarySearch l element
BinarySearch makeTree 5