package tree import ( "regexp" "sort" ) type Node struct { Name rune Parents []*Node Children []*Node Worked int // the amount of time spent working on this node. } // BuildDependencyTree parses the input and returns the root node. func BuildDependencyTree(data []string) *Node { depMap := make(map[rune]*Node) parentRegex := regexp.MustCompile("Step ([A-Z]) must") childRegex := regexp.MustCompile("step ([A-Z]) can begin") for _, line := range data { parent := rune(parentRegex.FindSubmatch([]byte(line))[1][0]) child := rune(childRegex.FindSubmatch([]byte(line))[1][0]) // Create the nodes if they don't exist if depMap[parent] == nil { depMap[parent] = &Node{Name: parent} } if depMap[child] == nil { depMap[child] = &Node{Name: child} } // Get each node and add the dependency info. pNode := depMap[parent] cNode := depMap[child] pNode.Children = append(pNode.Children, cNode) cNode.Parents = append(cNode.Parents, pNode) } // sort the children in each node for _, node := range depMap { sortNodes(node.Children) } return BuildTreeRoot(depMap) } func sortNodes(nodes []*Node) { sort.Slice(nodes[:], func(i, j int) bool { return nodes[i].Name < nodes[j].Name }) } func BuildTreeRoot(depMap map[rune]*Node) *Node { root := &Node{Name: 0} for _, node := range depMap { if len(node.Parents) == 0 { root.Children = append(root.Children, node) node.Parents = append(node.Parents, root) } } sortNodes(root.Children) return root }