68 lines
1.5 KiB
Go
68 lines
1.5 KiB
Go
package day07
|
|
|
|
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
|
|
}
|