package day07 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 }