Den 7. byl opět jeden z drsnějších, ale nakonec se podařilo 🙂 .
import com.svetylkovo.rojo.Rojo import java.io.File import java.lang.StringBuilder data class Step(val name: String) : Comparable<Step> { val children = mutableListOf<Step>() var completed = false var remainingSeconds = (name.first().toInt() - 'A'.toInt() + 1) + 60 fun doWork() { if (--remainingSeconds < 1) completed = true } fun completeAndPrint() { completed = true print(name) } override fun compareTo(other: Step) = name.compareTo(other.name) } data class Worker(val name: String) { var stepInProgress: Step? = null fun doWork() = stepInProgress?.doWork() } fun main() { val stepsMap = mutableMapOf<String, Step>() val input = File("input7.txt").readText().trim() Rojo.forEach("Step (\\w+).+(\\w+) can", input) { name, subsequentName -> val step = stepsMap.computeIfAbsent(name) { Step(name) } step.children += stepsMap.computeIfAbsent(subsequentName) { Step(subsequentName) } } val allSteps = stepsMap.values.toList() //A processSteps(allSteps.findAvailableSteps(), allSteps) println() //B val workers = (1..5).map { Worker("Worker $it") } allSteps.forEach { it.completed = false } processStepsParallel(allSteps.findAvailableSteps(), allSteps, workers) } tailrec fun processStepsParallel( availableSteps: List<Step>, allSteps: List<Step>, workers: List<Worker>, doneSteps: StringBuilder = StringBuilder(), seconds: Int = 0 ) { if (availableSteps.isNotEmpty()) { workers.forEach { it.run { doWork() if (stepInProgress?.completed == true) { doneSteps.append(stepInProgress?.name) stepInProgress = null } } } assignWork(workers, allSteps) println("Second $seconds, ${workers.joinToString(" ") { "${it.name}: ${it.stepInProgress?.name ?: "."}" }}, Done: $doneSteps") return processStepsParallel(allSteps.findAvailableSteps(), allSteps, workers, doneSteps, seconds + 1) } val realSeconds = seconds - 1 println("Elapsed seconds: $realSeconds") } private fun assignWork( workers: List<Worker>, allSteps: List<Step> ) { val unassignedSteps = allSteps.findAvailableSteps() .filterNot { step -> workers.any { it.stepInProgress == step } } workers.filter { it.stepInProgress == null } .zip(unassignedSteps) { worker, step -> worker.stepInProgress = step } } tailrec fun processSteps(availableSteps: List<Step>, allSteps: List<Step>) { if (availableSteps.isNotEmpty()) { availableSteps.first().completeAndPrint() processSteps(allSteps.findAvailableSteps(), allSteps) } } private fun List<Step>.findAvailableSteps() = filter { !it.completed } .filter { findPendingDependenciesFor(it).isEmpty() } .sorted() private fun List<Step>.findPendingDependenciesFor(step: Step) = filter { !it.completed } .filter { it.children.any { it.name == step.name } }