diff --git a/2018/day07-2.go b/2018/day07-2.go new file mode 100644 index 0000000..a282213 --- /dev/null +++ b/2018/day07-2.go @@ -0,0 +1,19 @@ +package main + +import ( + "fmt" + + "internal/tree" + "internal/util" +) + +func main() { + data := util.ReadInput() + + // Build a tree of dependencies. + root := tree.BuildDependencyTree(data) + + // Build + time := tree.SimulateConstruction(root) + fmt.Println(time) +} diff --git a/2018/internal/tree/construction.go b/2018/internal/tree/construction.go new file mode 100644 index 0000000..e4355b1 --- /dev/null +++ b/2018/internal/tree/construction.go @@ -0,0 +1,54 @@ +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 +} diff --git a/2018/internal/tree/tree.go b/2018/internal/tree/tree.go index 9479098..65b8244 100644 --- a/2018/internal/tree/tree.go +++ b/2018/internal/tree/tree.go @@ -9,6 +9,7 @@ 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.