All Downloads are FREE. Search and download functionalities are using the official Maven repository.

fuookami.ospf.kotlin.utils.math.combinatorics.Permutations.kt Maven / Gradle / Ivy

There is a newer version: 1.0.29
Show newest version
package fuookami.ospf.kotlin.utils.math.combinatorics

import java.util.Collections.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import org.apache.logging.log4j.kotlin.*
import fuookami.ospf.kotlin.utils.parallel.*

// A Counting QuickPerm Algorithm
fun  permute(input: List): List> {
    val a = input.toList()
    val p = input.indices.map { 0 }.toMutableList()

    val perms = ArrayList>()
    perms.add(a.toList())

    var i = 1;
    while (i < input.size) {
        if (p[i] < i) {
            val j = i % 2 * p[i]
            swap(a, i, j)
            perms.add(a.toList())
            p[i] += 1;
            i = 1
        } else {
            p[i] = 0;
            ++i;
        }
    }
    return perms
}

fun  permuteCallBack(
    input: List,
    callBack: (List) -> Unit,
    stopped: ((List) -> Boolean)? = null
) {
    var value: List

    val a = input.toList()
    val p = input.indices.map { 0 }.toMutableList()
    value = a.toList()
    callBack(value)
    if (stopped?.invoke(value) == true) {
        return
    }

    var i = 1;
    while (i < input.size) {
        if (p[i] < i) {
            val j = i % 2 * p[i]
            swap(a, i, j)
            value = a.toList()
            callBack(value)
            if (stopped?.invoke(value) == true) {
                return
            }
            p[i] += 1;
            i = 1
        } else {
            p[i] = 0;
            ++i;
        }
    }
}

@OptIn(DelicateCoroutinesApi::class)
fun  permuteAsync(input: List, scope: CoroutineScope = GlobalScope): ChannelGuard> {
    val logger = logger("Permutations")

    val promise = Channel>(Channel.UNLIMITED)
    scope.launch(Dispatchers.Default) {
        try {
            val a = input.toList()
            val p = input.indices.map { 0 }.toMutableList()
            if (!promise.isClosedForSend) {
                promise.send(a.toList())
            }

            var i = 1;
            while (i < input.size && !promise.isClosedForSend) {
                if (p[i] < i) {
                    val j = i % 2 * p[i]
                    swap(a, i, j)
                    if (promise.isClosedForSend) {
                        break
                    }
                    promise.send(a.toList())
                    p[i] += 1;
                    i = 1
                } else {
                    p[i] = 0;
                    ++i;
                }
            }
        } catch (e: ClosedSendChannelException) {
            logger.debug { "Permutation generation was stopped by controller." }
        } catch (e: Exception) {
            logger.debug { "Permutation generation Error ${e.message}" }
        } finally {
            promise.close()
        }
    }
    return ChannelGuard(promise)
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy