How can I convert a tree to a list:
So far I have the following code but its giving several issues:
type 'a tree = Lf | Br of 'a * 'a tree * 'a tree;;
let rec elementRight xs = function
| LF ->false
| Br(m,t1,t2) -> if elementRight xs t1 = false then t1::xs else element xs t1;; //cannot find element
let rec elementLeft xs = function
| LF ->false
| Br(m,t1,t2) -> if elementLeft xs t2 = false then t2::xs else element xs t2 ;; //cannot find element
let rec element xs = function
| LF ->[]
| Br(m,t1,t2) -> xs::(elementRight xs t1)::(elementRight xs t2)::(elementLeft xs t1)::(elementLeft xs t2);;
There are a number of problems with your code:
You shouldn't have ;; at the end of lines (I'm guessing this means you're copy and pasting into the repl, you should really use an fsx file instead and use "send to repl").
This: | LF ->false is returning a bool, while this: | Br(m,t1,t2) -> if elementRight xs t1 = false then t1::xs else element xs t1 is returning an 'a list. An expression can only have one type, so returning two is a compile error. I'm guessing what you really are meaning to do is have the leaf return [] and then check for empty list in your branch case something like this:
let rec elementRight xs = function
| LF ->[]
| Br(m,t1,t2) -> if elementRight xs t1 = List.empty then t1::xs else element xs t1
3 . when using mutually recursive functions you need to use the and keyword for all declarations but the first like this:
let rec elementRight xs = function
...
and elementLeft xs = function
...
and element xs = function
...
Related
tldr; go to My Question
I believe that the problem presented here must not be at all new, but I have failed to find any directly corresponding discussion.
Let's say that I have the following function (in order to provide a deterministic substitute for a real-world function having the same structural properties, of type 'a -> 'a seq):
// I'm a function that looks suspiciously like a tree
let lsExample x =
match x with
| 0 -> seq { 1; 6; 7 }
| 1 -> seq { 2; 3 }
| 3 -> seq { 4; 5 }
| 7 -> seq { 8; 9 }
| _ -> Seq.empty
Now, I wish to have the following:
let lsAll: ('a -> 'a seq) -> 'a -> 'a seq
such that
lsAll lsExample 0
evaluates to
seq { 0 .. 9 }
I have found one long-winded solution to this, and one simple, but still not ideal, solution to a similar problem.
Solution 1
Convert the ls function to a Rose Tree, then do a pre-order dfs on the tree, as follows:
open FSharpx.Collections
module L = LazyList
module R = Experimental.RoseTree
let rec asRoseTree (ls: 'a -> seq<'a>) (item: 'a) =
let children = ls item
if (Seq.isEmpty children) then
R.singleton item
else
children
|> Seq.map (asRoseTree ls)
|> L.ofSeq
|> R.create item
let lsAll ls =
asRoseTree ls >> R.dfsPre
Solution 2
Having got the job done, I wanted a more elegant solution, so started with this approximation using 'a -> 'a list (lists offer structural pattern matching, whereas seqs don't... I hope no one ever uses this implementation):
let rec lsAll' (ls: 'a -> 'a list) (xs: 'a list) =
match xs with
| [] -> []
| [x] -> lsAll' ls (ls x) |> List.append [x]
| x :: tail -> lsAll' ls tail |> List.append (lsAll' ls [x])
let lsAll ls x = lsAll' ls [x]
I then got stumped trying to make this tail-recursive, even without the extra inconvenience of switching back to seq.
My question
How can we implement lsAll:
without resorting to constructing an intermediate, explicit tree structure;
with the desired types (seq, not list);
using tail recursion (a case for CPS?); and
without explicit self recursion (e.g. use a fold with accumulator/cps)?
Aside: Having got the job done and written this question up, I'm now thinking that getting the input function into a tree structure might not be a waste at all, and I should have made better use of it. That said, I'm still too curious to give up on this quest!
You can do this very nicely using F# sequence expressions and the yield and yield! constructs:
let rec lsAll ls x = seq {
yield x
for c in ls x do
yield! lsAll ls c }
lsAll lsExample 0
A sequence expression seq { .. } is a code block that generates a sequence. Inside this, you can use yield to add a single element to the sequence but also yield! to add all elements of some other sequence. Here, you can do this to include all values produced by a recursive call.
You could combine this with the approach in your solution 2 too:
let rec lsAll ls xs = seq {
match xs with
| [] -> ()
| x::xs ->
yield x
yield! lsAll ls (ls x)
yield! lsAll ls xs }
This requires lsAll to return a list - you could insert List.ofSeq on the line before the last, but I think it's probably best to leave this to the user. However, you can now turn this into tail-recursive version by using CPS where the continuation is "sequence of values to be produced after the current one is done":
let rec lsAll ls xs cont = seq {
match xs with
| [] -> yield! cont
| x::xs ->
yield x
yield! lsAll ls (ls x) (lsAll ls xs cont) }
lsAll (lsExample >> List.ofSeq) [0] Seq.empty
If I give this an infinite tree, it does not actually StackOverflow, but keeps allocating more and more memory, so I guess it works!
let rec contains (x: int list)(y: int) : bool =
begin match x with
| [] -> false
| [y] -> true
| hd::tail -> (hd = y) && (contains tail y)
end
I'm not sure where I'm going wrong in my pattern matching but for any non-empty list I input, I keep getting "true" as my return type, when I want it to return true only if the input int exists in the list.
You have several problems.
The first is you use pattern matching to check if the list is exactly [y].
This is not how it works, it will actually match any list with exactly one element.
If you want to state equalities like that you can use when clauses.
let rec contains (l : int list) (y : int) : bool =
begin match l with
| [] -> false
| [z] when z = y -> true
| [z] -> false
| hd :: tl -> hd = y && contains tl y
end
The first [z] when z = y will trigger on a list containing exactly your y.
The second clause [z] will trigger on the rest.
Then, there is the problem of your last case: y belongs to hd :: tl if it is hd or if it belongs in tl. You used and, so that couldn't be right.
This gives us:
let rec contains (l : int list) (y : int) : bool =
begin match l with
| [] -> false
| [z] when z = y -> true
| [z] -> false
| hd :: tl -> hd = y || contains tl y
end
Of course this can even be simplified.
let rec contains (l : int list) (y : int) : bool =
begin match l with
| [] -> false
| hd :: tl -> hd = y || contains tl y
end
Indeed there is no need to make a special case of the list with one element.
[y] is the same as y :: [].
So to sum it up, if the element is in the head you got it, otherwise you go look in the tail, and so on until you reach the empty list which means you didn't find it.
How would I go about adding sub-lists.
For example, [ [10;2;10]; [10;50;10]] ----> [20;52;20] that is 10+10, 2+50 and 10+10. Not sure how to start this.
Fold is a higher order function:
let input = [[10;2;10]; [10;50;10]]
input |> Seq.fold (fun acc elem -> acc + (List.nth elem 1)) 0
val it : int = 52
Solution 1: Recursive version
We need a helper function to add two lists by summing elements one-to-one. It is recursive and assumes that both lists are of the same length:
let rec sum2Lists (l1:List<int>) (l2:List<int>) =
match (l1,l2) with
| ([],[]) -> []
| (x1::t1, x2::t2) -> (x1+x2)::sum2Lists t1 t2
Then the following recursive function can process a list of lists, using our helper function :
let rec sumLists xs =
match xs with
| [] -> [] // empty list
| x1::[] -> x1 // a single sublist
| xh::xt -> sum2Lists xh (sumLists xt) // add the head to recursion on tail
let myres = sumLists mylist
Solution 2: higher order function
Our helper function can be simplified, using List.map2:
let sum2hfLists (l1:List<int>) (l2:List<int>) = List.map2 (+) l1 l2
We can then use List.fold to create an on the flow accumulator using our helper function:
let sumhfList (l:List<List<int>>) =
match l with
| [] -> [] // empty list of sublist
| h::[] -> h // list with a single sublist
| h::t -> List.fold (fun a x -> sum2hfLists a x) h t
The last match case is applied only for lists of at least two sublists. The trick is to take the first sublist as starting point of the accumulator, and let fold execute on the rest of the list.
So I am trying to print a list of lists that would look like this:
[0;0;0;0;0];
[0;0;0;0;0];
[0;0;1;0;0];
[0;0;0;0;0];
I can use as many functions as necessary, but only one function may use a print function. Here is what I have so far:
let rec rowToString(row) =
if (row == []) then []
else string_of_int(List.hd row) :: ";" :: rowToString(List.tl row);;
let rec pp_my_image s =
print_list(rowToString(List.hd s)) :: pp_my_image(List.tl s);;
I know this is wrong, but I can't figure out a way to do it.
Here is one way to do it:
let rec rowToString r =
match r with
| [] -> ""
| h :: [] -> string_of_int h
| h :: t -> string_of_int h ^ ";" ^ (rowToString t)
let rec imageToString i =
match i with
| [] -> ""
| h :: t -> "[" ^ (rowToString h) ^ "];\n" ^ (imageToString t)
let pp_my_image s =
print_string (imageToString s)
The rowToString function will create a string with the items in each inner list. Notice that case h :: [] is separated so that a semicolon is not added after the last item.
The imageToString function will create a string for each inner list with a call to rowToString. It will surround the result of each string with brackets and add a semicolon and newline to the end.
pp_my_image will simply convert the image to a string and print the result.
I am trying to input a list into the function and it send me a list with the first half of the elements taken away using f# with the below recursion but I keep running into a base case problem that I just cant figure out. any thoughts? I am using the second shadow list to count how far I need to go until I am half way into the list (by removing two elements at a time)
let rec dropHalf listToDrop shadowList =
match shadowList with
| [] -> listToDrop
| shadowHead2::shadowHead1::shadowTail -> if shadowTail.Length<=1 then listToDrop else
match listToDrop with
|[] -> listToDrop
|listToDropHead::listToDropTail -> dropHalf listToDropTail shadowTail
let rec dropHalf listToDrop shadowList =
match shadowList with
| [] -> listToDrop
| shadowHead2::[] -> listToDrop (* odd number! *)
| shadowHead1::shadowHead2::shadowTail ->
match listToDrop with
| [] -> listToDrop (* should never happen? *)
| listToDropHead::listToDropTail -> dropHalf listToDropTail shadowTail
i'm afraid i don't use F#, but it's similar to ocaml, so hopefully the following is close to what you're looking for (maybe the comment format has changed?!). the idea is that when you exhaust the shadow you're done. your code was almost there, but the test for length on the shadow tail made no sense.
i want to emphasize that this isn't anything like anyone would write "in real life", but it sounds like you're battling with some weird requirements.
Because you use the shadow list with the same length as the original list and remove elements from these lists with different rates, it's better to create an auxiliary function:
let dropHalf xs =
let rec dropHalf' ys zs =
match ys, zs with
| _::_::ys', _::zs' -> dropHalf' ys' zs'
| _, zs' -> zs' (* One half of the shadow list ys *)
dropHalf' xs xs
If you don't care to traverse the list twice, the following solution is simpler:
let rec drop n xs =
match xs, n with
| _ when n < 0 -> failwith "n should be greater or equals to 0"
| [], _ -> []
| _, 0 -> xs
| _::xs', _ -> drop (n-1) xs'
let dropHalf xs =
xs |> drop (List.length xs/2)
and another simple solution needs some extra space but doesn't have to use recursion:
let dropHalf xs =
let xa = Array.ofList xs
xa.[xa.Length/2..] |> List.ofArray
As a general rule of thumb, if you're calling Length on a list, then there is most likely a better way to do what you're doing. Length has to iterate the entire list and is therefore O(n).
let secondHalf list =
let rec half (result : 'a list) = function
| a::b::sx -> half result.Tail sx
// uncomment to remove odd value from second half
// | (a::sx) -> result.Tail
| _ -> result
half list list
Here is a sample does what you described.
open System
open System.Collections.Generic
let items = seq { 1 .. 100 } |> Seq.toList
let getBackOfList ( targetList : int list) =
if (targetList.Length = 0) then
targetList
else
let len = targetList.Length
let halfLen = len / 2
targetList |> Seq.skip halfLen |> Seq.toList
let shortList = items |> getBackOfList
("Len: {0}", shortList.Length) |> Console.WriteLine
let result = Console.ReadLine()
Hope this helps