2 of 4 edited tags

Regrowing trees

Background

Here you have another work-inspired challenge, but from my wife's work in this case. Imagine you have a service that returns the list of nodes in a tree structure (much like the files and folders in a file system), but in no particular order. For every node you get a tuple with its name and the name of its parent.

So if you get [["C","B"],["D","C"],["A",""],["B","A"]] (format: [NodeName,ParentName]), you could rebuild the tree structure and get a leaf with the path /A/B/C/D (A has no parent, then it is at the top level, then B is a child of A, C is a child of B and D is a child of C).

You could also get [["C","B"],["D","C"],["A",""],["B","A"],["E","B"]], so the rebuilt tree would contain two leaves: one with the path /A/B/C/D (the same as in the previous example) and a new one with the path /A/B/E as the node E has B as its parent. Note that the nodes in the list are not duplicated (the leaves D and E have parts of their paths coincident but the common parts do not appear twice in the original list of nodes).

Challenge

Given a list of nodes as described above, rebuild the tree and output the paths for all the leaves in the tree structure, in no particular order as long as you return them all.

Rules

  • The input will be a list of tuples with two elements each: the name of the current node and the name of its parent. If you don't like strings you can use arrays of chars. You can choose the order of the elements in the tuple (the node name first or the parent name first).
  • The output format depends on you, as long as the paths for each leaf can be reconstructed. You can return a list of paths as strings like ["/A/B/C/D","/A/B/E"] for the second example, or return a list of path nodes for each leaf, as in [["A","B","C","D"],["A","B","E"]] for the same example, or even return a dictionary (something like ["A":["B":["E":[],"C":["D":[]]]]]). Or just print the list of paths to STDOUT.
  • There won't be nodes without a parent given explicitly.
  • The node names will be strings of alphanumeric ASCII characters [a-zA-Z0-9] of any length. So you can use any other printable ASCII character as separator if you decide to print or return the paths as strings.
  • There won't be duplicated tuples in the list.
  • There won't be cyclic paths in the list of nodes.
  • The node names are case sensitive. Nodes aa and AA are not the same node.
  • If you get an empty list of nodes, return an empty list/dictionary of leaves (or just print nothing).

Test cases

In:  [["C","B"],["D","C"],["A",""],["B","A"],["E","B"]]
Out: /A/B/C/D
     /A/B/E
Alt: [["A","B","C","D"],["A","B","E"]]
Alt: ["A":["B":["E":[],"C":["D":[]]]]]

In:  [["D3","D8"],["D5","d1"],["s2","S1"],["S1",""],["d1",""],["D8","D5"],["F4","s2"],["F7","S1"],["e3","D5"]]
Out: /d1/D5/D8/D3
     /d1/D5/e3
     /S1/s2/F4
     /S1/F7
Alt: [["d1","D5","D8","D3"],["d1","D5","e3"],["S1","s2","F4"],["S1","F7"]]
Alt: ["d1":["D5":["e3":[],"D8":["D3":[]]]],"S1":["F7":[],"s2":["F4":[]]]]

In:  [["Top",""]]
Out: /Top
Alt: [["Top"]]
Alt: ["Top":[]]

In:  []
Out: 
Alt: []
Alt: []

This is , so may the shortest code for each language win!


This comes from the sandbox (for those who can see deleted posts).