Skip to content

Instantly share code, notes, and snippets.

@irsalshabirin
Last active March 10, 2020 08:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save irsalshabirin/5dc50a99665f88444c6013ba23c33cd4 to your computer and use it in GitHub Desktop.
Save irsalshabirin/5dc50a99665f88444c6013ba23c33cd4 to your computer and use it in GitHub Desktop.
find lost number using coroutine
import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis
/**
* **************** FIND THE LOST NUMBER ********************
*
* explanation :
* find the number that does not exist in [arr].
*
* The rule :
* 1. the number must be greater than zero (number > 0)
* 2. [arr] can contains a negative number. (ex: arr = [-2, -100, 100])
* 3. [arr] can contains same number. (ex : [array] = [1, 2, 2, 3])
*
* solution 1 :
* just doing a for loop 1 until (max number + 1) then check if the index of iteration not included in [arr].
* Then give the return value of index.
*
* solution 2 :
* using coroutine and give n threads to find each block [arr].
*
* [arr] will be chunked into [chunkedArrs].
* For example : [arr] = [1, 2, 3, 4], n_thread = 2
* so, [chunkedArrs] : [[1, 2], [3, 4]].
*
* each value of [chunkedArrs] will be proceed with the different thread.
* so each process can be asynchronous or not sequential.
*
*/
val arr = (1..10_000).toMutableList()
// .apply {
// remove(50_000)
// }
fun main() = runBlocking<Unit> {
async(Dispatchers.Default) {
val time = measureTimeMillis { findLostNumber(arr) }
log("not async - take time : $time")
log("--------------")
}
async(Dispatchers.Default) {
val time = measureTimeMillis {
try {
findLostNumberAsync(arr, thread = 1_000)
} catch (e: CancellationException) {
// log(e.message ?: "")
}
}
log("async - take time : $time")
log("--------------")
}
}
suspend fun findLostNumberAsync(arr: List<Int>, thread: Int) = coroutineScope {
val customArrs = arr.toSet().filter { it > 0 }.sorted()
/** make sure count of [thread] not bigger than [customArrs.size] */
val customThread = if (customArrs.size < thread) {
customArrs.size
} else {
thread
}
val chunkedArrs = customArrs.chunked(customArrs.size / customThread)
repeat(customThread) { index ->
async(Dispatchers.Default) {
val start = if (index == 0) {
1
} else {
chunkedArrs[index - 1].last()
}
val finish = chunkedArrs[index].last()
fun cancelJob(number: Int) {
log("async founded in : $number")
this@coroutineScope.cancel(CancellationException("async founded in : $number"))
}
var isFounded = false
for (i in start..finish) {
isFounded = !customArrs.contains(i)
if (isFounded) {
cancelJob(i)
}
}
/** on last chunked */
if (index == customThread - 1 && !isFounded && isActive) {
cancelJob(customArrs.last() + 1)
}
}
}
}
fun findLostNumber(arr: List<Int>) {
val customArrs = arr.toSet().filter { it > 0 }.sorted()
val maxVal = customArrs.max() ?: 0 + 1
for (i in 1..maxVal + 1) {
if (!customArrs.contains(i)) {
log("not async founded : $i")
break
}
}
}
fun log(v: Any) = println("[${Thread.currentThread().name}] $v")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment