As an additional challenge, I added a record of the order shoppers finish.
internal sealed class Cashier internal data class Occupied(val timeleft: Int, val shopper: Shopper) : Cashier() { constructor(shopper: Shopper) : this(shopper.time - 1, shopper) } internal object Ready : Cashier() data class Shopper(val id: Int, val time: Int) private fun queueTimeAndFinishOrder(shoppers: List<Int>, cashiers: Int) = simulateWithOrder( Moment( waitingShoppers = shoppers.mapIndexed { i, it -> Shopper(i + 1, it) }, aisles = generateSequence { Ready }.take(cashiers).toList() ) ) private data class Moment( val waitingShoppers: List<Shopper>, val aisles: List<Cashier> = emptyList(), val finishedShoppers: List<Shopper> = emptyList(), val tick: Int = 0 ) private tailrec fun simulateWithOrder( moment: Moment ): Moment { val nextMoment = moment.aisles.fold( Moment( waitingShoppers = moment.waitingShoppers, finishedShoppers = moment.finishedShoppers, tick = moment.tick + 1 ) ) { (waiting, aisles, finished, tick): Moment, aisle -> when { aisle is Ready && waiting.isNotEmpty() -> Moment( waitingShoppers = waiting.drop(1), aisles = aisles + Occupied(waiting.first()), finishedShoppers = finished, tick = tick ) aisle is Occupied && aisle.timeleft <= 1 -> Moment( waitingShoppers = waiting, aisles = aisles + aisle.tickDown(), finishedShoppers = finished + aisle.shopper, tick = tick ) aisle is Occupied -> Moment( waitingShoppers = waiting, aisles = aisles + aisle.tickDown(), finishedShoppers = finished, tick = tick ) else -> Moment( waitingShoppers = waiting, aisles = aisles + aisle, finishedShoppers = finished, tick = tick ) } } return when { nextMoment.waitingShoppers.isEmpty() && nextMoment.aisles.all { it is Ready } -> nextMoment else -> simulateWithOrder(nextMoment) } } private fun Occupied.tickDown() = when (timeleft) { 1 -> Ready else -> Occupied(timeleft - 1, shopper) } fun main() { val momentA = queueTimeAndFinishOrder(listOf(5, 3, 4), 1) println("time: ${momentA.tick}, order: [${momentA.finishedShoppers.joinToString { "${it.id}" }}]") val momentB = queueTimeAndFinishOrder(listOf(10, 2, 3, 3), 2) println("time: ${momentB.tick}, order: [${momentB.finishedShoppers.joinToString { "${it.id}" }}]") val momentC = queueTimeAndFinishOrder(listOf(2, 3, 10), 2) println("time: ${momentC.tick}, order: [${momentC.finishedShoppers.joinToString { "${it.id}" }}]") }
Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink.
Hide child comments as well
Confirm
For further actions, you may consider blocking this person and/or reporting abuse
We're a place where coders share, stay up-to-date and grow their careers.
As an additional challenge, I added a record of the order shoppers finish.