55 lines
1.1 KiB
Go
55 lines
1.1 KiB
Go
package tree
|
|
|
|
func SimulateConstruction(root *Node) int {
|
|
working := make(map[rune]*Node)
|
|
done := map[rune]bool{
|
|
0: true,
|
|
}
|
|
elapsed := 0
|
|
|
|
for {
|
|
// returns true when no work is left to do.
|
|
if tick(root, working, done) {
|
|
return elapsed
|
|
}
|
|
|
|
elapsed++
|
|
}
|
|
}
|
|
|
|
func tick(root *Node, working map[rune]*Node, done map[rune]bool) bool {
|
|
complete := true
|
|
|
|
// Find candidates, if we need new ones.
|
|
if len(working) < 5 {
|
|
candidates := findCandidates(root, done)
|
|
for _, candidate := range candidates {
|
|
if len(working) >= 5 {
|
|
break
|
|
}
|
|
|
|
// if we see a candidate that we can work on, put it in the map.
|
|
if working[candidate.Name] == nil {
|
|
working[candidate.Name] = candidate
|
|
complete = false
|
|
}
|
|
}
|
|
}
|
|
|
|
// work on each in-progress node.
|
|
for _, node := range working {
|
|
complete = false
|
|
node.Worked++
|
|
|
|
// if we're done, add it to done and delete from worker queue
|
|
// `-4` is exploiting the fact that the rune capital A is value
|
|
// 65 as an integer (and so on)
|
|
if node.Worked >= int(node.Name)-4 {
|
|
done[node.Name] = true
|
|
delete(working, node.Name)
|
|
}
|
|
}
|
|
|
|
return complete
|
|
}
|