Once I got there, I found part 2 to be a fairly straightforward extension to parallelise the work and keep track of remaining time. One trick was to make the Work ordering put in-progress work first, so on each iterations the workers pulled active steps from the stack first.
I was convinced at first I could sort the steps like this:
It worked on the test data, but not on the full problem. I was really frustrated for a while, and had to google it, coming up with Kahn's algorithm
I went through an imperative, mutation-heavy version first but my Kotlin for part 1 ended up like this:
Once I got there, I found part 2 to be a fairly straightforward extension to parallelise the work and keep track of remaining time. One trick was to make the
Work
ordering put in-progress work first, so on each iterations the workers pulled active steps from the stack first.