1

I have a tree represented by

type LazyTree<'T> =
    | LazyBranch of 'T * ('T LazyTree list Lazy) 

I want to assign a number n to each node, counting left to right.

More formally

Edited:

For a node a, h(a)=0 if a has no children

For a node a with parent p, h(a)=h(p+1)

For a node a, without parent, L(a) is an empty set.

For a node a, which has a parent, L(a) is a set of all nodes where for each node i, path from root to it doesn't contain a

For a node a, S(a) is all elements of L(a), where for each element i holds h(i)<=h(a)

I need to replace value of each node a with size of S(a)

enter image description here

I cannot come up with a solution for my problem which does not involve side-effects.

My function should return a tree.

Its node is dependent on node of left sibling. So, the function should get a 'T LazyTree Option as a parameter.

But its leftmost child is dependent on our rightmost sibling which is dependent on us. It seems, we got an infinite cycle.

I'm not asking how to solve it on finite tree.


I'm not asking about an abstract concept. Here is how can I return one infinite tree from another:

type LazyTree<'T> =
    | LazyBranch of 'T * ('T LazyTree list Lazy)
with
    member this.Item = match this with LazyBranch(item,_) -> item
    member this.Children = match this with LazyBranch(_,children) -> children
member this.Map func =
        let children =
            lazy
            (
                this.Children.Force()
                |> List.map (fun child -> child.Map func)
            )
        LazyBranch(func this.Item, children)
user2136963
  • 2,526
  • 3
  • 22
  • 41
  • 2
    what solutions have you came up with and what side effects do they have? – Salvador Dali Jun 24 '16 at 05:24
  • I've come up with a solution for a finite tree. I just traversed it as a list, and then restored tree structure from that list. Wouldn't work there. I didn't try so solve it with side effects. – user2136963 Jun 24 '16 at 05:35
  • If you are voting to close, please tell in the comments, if you can solve it, al least without putting the solution. – user2136963 Jun 24 '16 at 05:51
  • I think I can solve it, but not with a recursion. I am writing think, because it is pretty unclear what exactly are you trying to achieve. From one point of view you assigns numbers to nodes in a layered fashion, from another point you tell that the function should return a tree without explaining what tree do you expect. – Salvador Dali Jun 24 '16 at 05:57
  • I even drew a tree to make it clearer. From a tree with arbitrary nodes structured like on the picture get exact tree on the picture (assuming that lower nodes have some infinite trees as children) – user2136963 Jun 24 '16 at 06:01
  • Then why should it return any other tree, if all you do is just assign values to an already created tree. Also how can it potentially return anything for an infinite tree? Based on my understanding it should work till it is stopped and at any point of time it has some values assigned to a node. – Salvador Dali Jun 24 '16 at 06:10
  • Because I want to save my structure. I cannot assign it if I want to stay in a functional paradigm. Returning to your first question, it would be possible to create an infinite tree of `None`s have some kind of mutator, which traverses tree and mutates its node one by one to `Some x`. Then, when I want a solution for a partucular node, I would do `while "this node has None" do "Mutate"` – user2136963 Jun 24 '16 at 06:21
  • How does the node with the value 4 get that value? According to the description, its parent has value 1, and as it's the sole child, it ought to have the value 2. – Mark Seemann Jun 24 '16 at 16:58
  • I'm voting to close this question as off-topic because it deals with an abstract concept, not an actual programming problem. – Prune Jun 24 '16 at 17:35
  • @user2136963 -- your "formal" description does not match the tree. First, your middle rule depends only on the value of the parent node (per Mark), you depends on the max of the parent level. You touch on this in your later discussion, but you still haven't written an accurate rule. Second, you use "next to" freely when you seem to mean "to the immediate right of". Finally, Salvador's point is spot on: you can't ever return from labelling an infinite tree: that part of the program can't terminate. If you're asking for the abstract case, then you're asking on the wrong site altogether. – Prune Jun 24 '16 at 17:35
  • Thank you, I'm rewriting it. I can return another lazy structure. I provided `concrete` definition of a tree in `F#`. I can return another infinite tree like this `member this.Map func = let children = lazy ( this.Children.Force() |> List.map (fun child -> child.Map func) ) LazyBranch(func this.Item, children)` http://pastebin.com/M91uJFBc – user2136963 Jun 24 '16 at 17:57
  • 1
    Thank you for noticing mistake in my "formal" description. I corrected it. I still think, that the question does belong to this site. – user2136963 Jun 24 '16 at 18:10

2 Answers2

1

You're right that the recursion structure required here is somewhat intricate. Here's one approach. I'll use a helper function, number, which numbers a list of trees given the immediately preceding numbered tree as well as all numbered trees between this list and the first child of the first tree in this list. Then, if the list is non-empty:

  1. The tail of the desired list can be computed recursively, passing in the to-be-computed result of numbering the head of the list as the previous tree, and appending the children of that list to the "in-between" list, since they come before the second element's children.
  2. The numbered tree corresponding to the head of the list just takes the next number after its predecessor as its value. The children of this node can also be computed recursively. Consider all of the numbered trees between the one corresponding to the head and its children; this is slightly different than the existing in-between sequence, which only has the elements starting after the tail of this list, so we need to append the tail of the list computed in step 1 in front of the existing "in-between" list. Then the node immediately preceding the head node's first child is just the last element of this new in-between sequence if there is such an node, or the numbered tree itself if there isn't (this can happen if there are no nodes between a node and its children). And the nodes in between the children and their first children are just the children of this new in-between sequence.

Sorry if this description is unenlightening, but drawing a picture may help. Anyway, here's the corresponding code:

// These help with type inference
let value (LazyBranch(v,_)) = v
let children (LazyBranch(_,ts)) = ts.Value

let numberedTree =
    let rec number prev between = function
    | [] -> []
    | t::ts ->
        let rec rest = number first (seq { yield! between; yield! children first }) ts
        and first =
            let between' = seq { yield! rest; yield! between }
            LazyBranch(value prev + 1, lazy (children t |> number (defaultArg (Seq.tryLast between') first) (between' |> Seq.collect children)))
        first::rest
    fun t ->
        let rec result = LazyBranch(0, lazy number result [] (children t))
        result
kvb
  • 54,864
  • 2
  • 91
  • 133
-2

It is impossible to assign such numbers, because it will require (non-lazy) traversal of infinite tree. What you need is breadth-first traversal as in this pseudo code:

let traverse (node:LazyTree<'T>) =
     let q = System.Collections.Generic.Queue()
     q.Enqueue node
     let mutable i = 0
     while 0 < q.Count do // always TRUE
        let node = q.Dequeue ()
        printfn "Node #%i: %A" i node.Map
        i <- i + 1
        for child in node.Children.Force() do
            q.Enqueue child
Sergey OCHKIN
  • 67
  • 2
  • 2
  • I can produce such tree on paper, lazily, so it's possible to program. This code doesn't produce any trees, so it's irrelevant. Also, it's possible replace it with a lazy code: http://pastebin.com/FwnWnjCt – user2136963 Jul 03 '16 at 15:22