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
Related
Please, I need some help with creating an insert function for a tree. The value in a given string list should be inserted to every branch and leaf in a tree. I have tried to solve this issue and have a very close answer but I am not able to write the function correctly to insert all the string values.
Code:
type Tree = Leaf of string | Branch of (string * Tree) list
let rec insertTree (lst : string list) (tree : Tree) : Tree =
match lst, tree with
| a::b::c::[], y ->
match y with
| Leaf(n) -> Branch[(a, Branch[(n, Leaf(c))])]
| Branch[(x, p)] -> Branch[(x, Branch[(a, Branch[(b, insertTree (c::[]) p)])])]
| _ -> insertTree (b::c::[]) y
| _ , y -> tree
Test: insertTree ["4"; "5";"6"] (Branch [("1", (Branch[("2", Leaf("3"))]))])
Gives: Branch [("1", Branch [("4", Branch [("5", Branch [("2", Leaf "3")])])])]
I want this instead:
(Branch [("1", (Branch[("2", (Branch[("3",(Branch[("4",(Branch[("5", Leaf("6"))]))]))]))]))])
I'm going to assume you just want to append the list in order to the final leaf and that all branches will have at most a single element in its list.
let insertTree (lst : string list) (tree : Tree) : Tree =
let rec insertSingleIntotree x t =
match t with
| Leaf(n) -> Branch[(n,Leaf x)]
| Branch[(n,p)] -> Branch[(n, insertSingleIntotree x p)]
| _ -> failwith "no idea what should happen here!"
lst
|> List.fold (fun acc x -> insertSingleIntotree x acc) tree
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
I have a sequence of value that I would like to apply to a function partially :
let f a b c d e= a+b+c+d+e
let items = [1,2,3,4,5]
let result = applyPartially f items
Assert.Equal(15, result)
I am looking after the applyPartially function. I have tried writing recursive functions like this :
let rec applyPartially f items =
| [] -> f
| [x] -> f x
| head :: tail -> applyPartially (f head) tail
The problem I have encountered is that the f type is at the beginning of my iteration 'a->'b->'c->'d->'e, and for every loop it should consume an order.
'a->'b->'c->'d->'e
'b->'c->'d->'e
'c->'d->'e
'd->'e
That means that the lower interface I can think of would be 'd->'e. How could I hide the complexity of my function so that only 'd->'e is shown in the recursive function?
The F# type system does not have a nice way of working with ordinary functions in a way you are suggesting - to do this, you'd need to make sure that the length of the list matches the number of arguments of the function, which is not possible with ordinary lists and functions.
However, you can model this nicely using a discriminated union. You can define a partial function, which has either completed, or needs one more input:
type PartialFunction<'T, 'R> =
| Completed of 'R
| NeedsMore of ('T -> PartialFunction<'T, 'R>)
Your function f can now be written (with a slightly ugly syntax) as a PartialFunction<int, int> that keeps taking 5 inputs and then returns the result:
let f =
NeedsMore(fun a -> NeedsMore(fun b ->
NeedsMore(fun c -> NeedsMore(fun d ->
NeedsMore(fun e -> Completed(a+b+c+d+e))))))
Now you can implement applyPartially by deconstructing the list of arguments and applying them one by one to the partial function until you get the result:
let rec applyPartially f items =
match f, items with
| Completed r, _ -> r
| NeedsMore f, head::tail -> applyPartially (f head) tail
| NeedsMore _, _ -> failwith "Insufficient number of arguments"
The following now returns 15 as expected:
applyPartially f [1;2;3;4;5]
Disclaimer: Please don't use this. This is just plain evil.
let apply f v =
let args = v |> Seq.toArray
f.GetType().GetMethods()
|> Array.tryFind (fun m -> m.Name = "Invoke" && Array.length (m.GetParameters()) = Array.length args)
|> function None -> failwith "Not enough args" | Some(m) -> m.Invoke(f, args)
Just like you would expect:
let f a b c d e= a+b+c+d+e
apply f [1; 2; 3; 4; 5] //15
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 ->
I have two snippets of code that tries to convert a float list to a Vector3 or Vector2 list. The idea is to take 2/3 elements at a time from the list and combine them as a vector. The end result is a sequence of vectors.
let rec vec3Seq floatList =
seq {
match floatList with
| x::y::z::tail -> yield Vector3(x,y,z)
yield! vec3Seq tail
| [] -> ()
| _ -> failwith "float array not multiple of 3?"
}
let rec vec2Seq floatList =
seq {
match floatList with
| x::y::tail -> yield Vector2(x,y)
yield! vec2Seq tail
| [] -> ()
| _ -> failwith "float array not multiple of 2?"
}
The code looks very similiar and yet there seems to be no way to extract a common portion. Any ideas?
Here's one approach. I'm not sure how much simpler this really is, but it does abstract some of the repeated logic out.
let rec mkSeq (|P|_|) x =
seq {
match x with
| P(p,tail) ->
yield p
yield! mkSeq (|P|_|) tail
| [] -> ()
| _ -> failwith "List length mismatch" }
let vec3Seq =
mkSeq (function
| x::y::z::tail -> Some(Vector3(x,y,z), tail)
| _ -> None)
As Rex commented, if you want this only for two cases, then you probably won't have any problem if you leave the code as it is. However, if you want to extract a common pattern, then you can write a function that splits a list into sub-list of a specified length (2 or 3 or any other number). Once you do that, you'll only use map to turn each list of the specified length into Vector.
The function for splitting list isn't available in the F# library (as far as I can tell), so you'll have to implement it yourself. It can be done roughly like this:
let divideList n list =
// 'acc' - accumulates the resulting sub-lists (reversed order)
// 'tmp' - stores values of the current sub-list (reversed order)
// 'c' - the length of 'tmp' so far
// 'list' - the remaining elements to process
let rec divideListAux acc tmp c list =
match list with
| x::xs when c = n - 1 ->
// we're adding last element to 'tmp',
// so we reverse it and add it to accumulator
divideListAux ((List.rev (x::tmp))::acc) [] 0 xs
| x::xs ->
// add one more value to 'tmp'
divideListAux acc (x::tmp) (c+1) xs
| [] when c = 0 -> List.rev acc // no more elements and empty 'tmp'
| _ -> failwithf "not multiple of %d" n // non-empty 'tmp'
divideListAux [] [] 0 list
Now, you can use this function to implement your two conversions like this:
seq { for [x; y] in floatList |> divideList 2 -> Vector2(x,y) }
seq { for [x; y; z] in floatList |> divideList 3 -> Vector3(x,y,z) }
This will give a warning, because we're using an incomplete pattern that expects that the returned lists will be of length 2 or 3 respectively, but that's correct expectation, so the code will work fine. I'm also using a brief version of sequence expression the -> does the same thing as do yield, but it can be used only in simple cases like this one.
This is simular to kvb's solution but doesn't use a partial active pattern.
let rec listToSeq convert (list:list<_>) =
seq {
if not(List.isEmpty list) then
let list, vec = convert list
yield vec
yield! listToSeq convert list
}
let vec2Seq = listToSeq (function
| x::y::tail -> tail, Vector2(x,y)
| _ -> failwith "float array not multiple of 2?")
let vec3Seq = listToSeq (function
| x::y::z::tail -> tail, Vector3(x,y,z)
| _ -> failwith "float array not multiple of 3?")
Honestly, what you have is pretty much as good as it can get, although you might be able to make a little more compact using this:
// take 3 [1 .. 5] returns ([1; 2; 3], [4; 5])
let rec take count l =
match count, l with
| 0, xs -> [], xs
| n, x::xs -> let res, xs' = take (count - 1) xs in x::res, xs'
| n, [] -> failwith "Index out of range"
// split 3 [1 .. 6] returns [[1;2;3]; [4;5;6]]
let rec split count l =
seq { match take count l with
| xs, ys -> yield xs; if ys <> [] then yield! split count ys }
let vec3Seq l = split 3 l |> Seq.map (fun [x;y;z] -> Vector3(x, y, z))
let vec2Seq l = split 2 l |> Seq.map (fun [x;y] -> Vector2(x, y))
Now the process of breaking up your lists is moved into its own generic "take" and "split" functions, its much easier to map it to your desired type.