I have a non-binary tree with the following structure:
Note: The coefficients refer only to how many child node variables exist within 1 parent node. The parent node's coefficient is thus irrelevant for this definition/assignment.
Note: The exact composition is random. Parents can have any number of children and different parents can have the same child (ie both F and B are comprised of E, though 1E and 4E respectively).
I have replicated this structure via dictionary:
dicts = {str:{str:int}}
dicts["A"] = {"B":2,"C":2,"D":1}
dicts["B"] = {"E":4}
dicts["C"] = {"F":4, "G":1}
dicts["F"] = {"E":1}
dicts["G"] = {"D":1,"E":1,"H":1}
I would ultimately like to describe each parent node in terms of only base layer child variables. That is, in terms of "E", "D", and "H", since these have no further children and are thus considered base layer. Mathematically, this involves getting to the root/base layer node, and multiplying the coefficients up to the parent. Ie, for A's left branch, it is comprised of 8E's. Then, a further 8 E's (via 2C -> 4F -> E) + 2 more E's (2C -> G -> E). A similar approach would be taken for "D" and "H".
Since the tree is non-binary and can have any number of children with any level of depth, I know I must utilize recursion to complete the definitions.
I have managed to build a script which correctly traverses down the first few legs, but as I moved to the other legs (or even just preemptively think of more complex, possible structures) I found that I needed to add increasing complexity to handle the varying paths. This made me feel I was approaching the problem incorrectly. Do I really need to nest more conditionals within the recursion? Or should I be approaching this differently?
Note: This loops infinitely after correctly traversing A->2B->4E & A->2C->4F->E (leading to {A:{E:16}}).
dicts = {str:{str:int}}
dicts["A"] = {"B":2,"C":2,"D":1}
dicts["B"] = {"E":4}
dicts["C"] = {"F":4, "G":1}
dicts["F"] = {"E":1}
dicts["G"] = {"D":1,"E":1,"H":1}
nullvalues = ["E","D","H"]
tempIntArray = []
tempCheckedArray = {str:[str]}
tempAnsweredArray = {str:{str:int}}
persistentN = ""
def recursive_traversal(n):
global persistentN
if persistentN == "":
persistentN = n
for x in dicts[n]:
if n not in tempCheckedArray.keys() or x not in tempCheckedArray[n]:
if x in nullvalues:
product = 1
tempIntArray.append(dicts[n][x])
for a in tempIntArray:
product = a * product
if persistentN in tempAnsweredArray.keys():
if x in tempAnsweredArray[persistentN].keys():
tempValue = tempAnsweredArray[persistentN][x] + product
tempAnsweredArray[persistentN][x] = tempValue
else:
tempAnsweredArray.update({persistentN:{x:product}})
else:
tempAnsweredArray.update({persistentN:{x:product}})
product = 1
if persistentN not in tempCheckedArray.keys():
tempCheckedArray[persistentN] = [n]
else:
tempCheckedArray[persistentN].append(n)
tempIntArray.clear()
return recursive_traversal(persistentN)
else:
tempIntArray.append(dicts[n][x])
return recursive_traversal(x)
recursive_traversal("A")
print(tempAnsweredArray)
The only path forward that I see with this present code block is to add in a check which searches a parsable string for the node paths already traveled and avoid them. Something like {"A": ["ABBC", "ACCFFE"]} and run a conditional to check if the path has been traversed or not. But again, this somehow feels like the wrong approach.