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

commonMain.korlibs.math.random.RandomExt.kt Maven / Gradle / Ivy

The newest version!
package korlibs.math.random

import korlibs.math.geom.*
import korlibs.math.interpolation.*
import kotlin.math.pow
import kotlin.random.Random

fun Random.ints(): Sequence = sequence { while (true) yield(nextInt()) }
fun Random.ints(from: Int, until: Int): Sequence = sequence { while (true) yield(nextInt(from, until)) }
fun Random.ints(range: IntRange): Sequence = ints(range.start, range.endInclusive + 1)

fun Random.doubles(): Sequence = sequence { while (true) yield(nextDouble()) }
fun Random.floats(): Sequence = sequence { while (true) yield(nextFloat()) }

fun  List.random(random: Random = Random): T {
    if (this.isEmpty()) throw IllegalArgumentException("Empty list")
    return this[random.nextInt(this.size)]
}

fun  List.randomWithWeights(weights: List, random: Random = Random): T = random.weighted(this.zip(weights).toMap())

fun Random.nextDoubleInclusive() = (this.nextInt(0x1000001).toDouble() / 0x1000000.toDouble())
fun Random.nextRatio(): Ratio = nextDouble().toRatio()
fun Random.nextRatioInclusive(): Ratio = nextDoubleInclusive().toRatio()

operator fun Random.get(min: Ratio, max: Ratio): Ratio = Ratio(get(min.valueD, max.valueD))
operator fun Random.get(min: Double, max: Double): Double = min + nextDouble() * (max - min)
operator fun Random.get(min: Float, max: Float): Float = min + nextFloat() * (max - min)
operator fun Random.get(min: Int, max: Int): Int = min + nextInt(max - min)
operator fun Random.get(range: IntRange): Int = range.start + this.nextInt(range.endInclusive - range.start + 1)
operator fun Random.get(range: LongRange): Long = range.start + this.nextLong() % (range.endInclusive - range.start + 1)
operator fun > Random.get(l: T, r: T): T = (this.nextDoubleInclusive()).toRatio().interpolate(l, r)
operator fun Random.get(l: Angle, r: Angle): Angle = this.nextRatioInclusive().interpolateAngleDenormalized(l, r)
operator fun  Random.get(list: List): T = list[this[list.indices]]
operator fun Random.get(rectangle: Rectangle): Point = Point(this[rectangle.left, rectangle.right], this[rectangle.top, rectangle.bottom])
fun > T.setToRandom(min: T, max: T, random: Random = Random) { this.setToInterpolated(random.nextDouble().toRatio(), min, max) }

fun  Random.weighted(weights: Map): T = shuffledWeighted(weights).first()
fun  Random.weighted(weights: RandomWeights): T = shuffledWeighted(weights).first()

fun  Random.shuffledWeighted(weights: Map): List = shuffledWeighted(RandomWeights(weights))
fun  Random.shuffledWeighted(values: List, weights: List): List = shuffledWeighted(RandomWeights(values, weights))
fun  Random.shuffledWeighted(weights: RandomWeights): List {
    val randoms = (0 until weights.items.size).map { -(nextDouble().pow(1.0 / weights.normalizedWeights[it])) }
    val sortedIndices = (0 until weights.items.size).sortedWith(Comparator { a, b -> randoms[a].compareTo(randoms[b]) })
    return sortedIndices.map { weights.items[it] }
}

data class RandomWeights(val weightsMap: Map) {
    constructor(vararg pairs: Pair) : this(mapOf(*pairs))
    constructor(values: List, weights: List) : this(values.zip(weights).toMap())

    val items = weightsMap.keys.toList()
    val weights = weightsMap.values.toList()
    val normalizedWeights = normalizeWeights(weights)

    companion object {
        private fun normalizeWeights(weights: List): List {
            val min = weights.minOrNull() ?: 0.0
            return weights.map { (it + min) + 1 }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy