Kotlin中如何正确校验所有Workstation是否被覆盖(单操作员仅负责一个)
Kotlin中工作站全覆盖的正确判断方案
问题背景
需要确保4个固定工作站(PANEL、OUTSIDE、MOVEMENTS、EXTRUDER)在部分操作员请假后仍能被完全覆盖,核心约束是每个操作员一次仅能负责一个工作站。
现有代码仅通过统计每个工作站的可操作人数判断覆盖情况,完全忽略了操作员的“唯一性”约束。例如当Paul和Alan请假后,原代码返回true,但实际场景中MOVEMENTS会因Jack需负责EXTRUDER、Andy需负责PANEL而无人覆盖。
现有问题代码
enum class WorkStations { PANEL, OUTSIDE, MOVEMENTS, EXTRUDER } data class Operator(val name: String, val workStations: List<WorkStations> = emptyList()) fun main() { val array = arrayListOf( Operator("Andy", listOf(WorkStations.PANEL, WorkStations.OUTSIDE, WorkStations.MOVEMENTS)), Operator("Alan", listOf(WorkStations.PANEL, WorkStations.OUTSIDE, WorkStations.MOVEMENTS)), Operator("Matt", listOf(WorkStations.OUTSIDE)), Operator("Paul", listOf(WorkStations.EXTRUDER, WorkStations.MOVEMENTS)), Operator("Jack", listOf(WorkStations.EXTRUDER, WorkStations.MOVEMENTS)), Operator("James", listOf(WorkStations.OUTSIDE)), Operator("Tall Paul"), Operator("Josh") ) fun areWorkStationsCovered(array: ArrayList<Operator>): Boolean { val newList = array.flatMap { it.workStations }.groupingBy { it }.eachCount().filter { it.value >= 1 } println(newList) return newList.size >= 4 } println(areWorkStationsCovered(array)) }
函数式解决方案
这个问题本质是二分图匹配问题:我们需要为每个工作站匹配一个唯一的、具备操作能力的操作员。以下是基于递归回溯的简洁实现,完全符合函数式编程风格:
enum class WorkStations { PANEL, OUTSIDE, MOVEMENTS, EXTRUDER } data class Operator(val name: String, val workStations: List<WorkStations> = emptyList()) fun main() { val allOperators = arrayListOf( Operator("Andy", listOf(WorkStations.PANEL, WorkStations.OUTSIDE, WorkStations.MOVEMENTS)), Operator("Alan", listOf(WorkStations.PANEL, WorkStations.OUTSIDE, WorkStations.MOVEMENTS)), Operator("Matt", listOf(WorkStations.OUTSIDE)), Operator("Paul", listOf(WorkStations.EXTRUDER, WorkStations.MOVEMENTS)), Operator("Jack", listOf(WorkStations.EXTRUDER, WorkStations.MOVEMENTS)), Operator("James", listOf(WorkStations.OUTSIDE)), Operator("Tall Paul"), Operator("Josh") ) // 测试全员在岗情况 println(areWorkStationsCovered(allOperators)) // 输出 true // 测试Paul和Alan请假后的情况 val operatorsAfterLeave = allOperators.filter { it.name !in listOf("Paul", "Alan") } println(areWorkStationsCovered(operatorsAfterLeave)) // 输出 false } fun areWorkStationsCovered(operators: List<Operator>): Boolean { val requiredStations = WorkStations.values().toList() val availableOperators = operators.filter { it.workStations.isNotEmpty() } return assignStations(requiredStations, availableOperators, emptySet()) } private fun assignStations( remainingStations: List<WorkStations>, availableOperators: List<Operator>, assignedOperators: Set<Operator> ): Boolean { // 所有工作站都分配完成,返回成功 if (remainingStations.isEmpty()) return true val currentStation = remainingStations.first() // 尝试为当前工作站分配所有符合条件且未被占用的操作员 return availableOperators .filter { currentStation in it.workStations && it !in assignedOperators } .any { operator -> // 递归分配剩余工作站,标记当前操作员已被占用 assignStations( remainingStations.drop(1), availableOperators, assignedOperators + operator ) } }
方案说明
- 核心逻辑:通过递归回溯尝试为每个工作站分配唯一的操作员,只要存在一种合法的分配方式覆盖所有4个工作站,就返回
true。 - 函数式特性:使用
filter、any等高阶函数处理集合,递归过程中通过不可变集合(Set)跟踪已分配的操作员,避免副作用。 - 边界处理:自动过滤掉没有任何工作站操作权限的操作员,减少无效计算。
内容的提问来源于stack exchange,提问作者Andy Cass
相关产品推荐
相关产品推荐

