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