package tree // FindOrder determines the correct order according to these rules: // 1. A node cannot come before all of its parents have been included. // 2. At any given time, the lowest-lettered available step must be executed. func FindOrder(root *Node) []*Node { seen := map[rune]bool{ 0: true, } order := []*Node{} for { // continuously loop over the tree, retrieving the next usable node. candidates := findCandidates(root, seen) if len(candidates) == 0 { return order } sortNodes(candidates) order = append(order, candidates[0]) seen[candidates[0].Name] = true } } func findCandidates(node *Node, seen map[rune]bool) []*Node { candidates := []*Node{} // if we've been seen before, we're clear to recurse if seen[node.Name] == true { for _, child := range node.Children { candidates = append(candidates, findCandidates(child, seen)...) } return candidates } // add the node, but only if all its parents have been seen for _, parent := range node.Parents { if seen[parent.Name] == false { return candidates } } // We haven't seen this one before, and its parents are seen. // Return it as a candidate. return append(candidates, node) }