commonMain.korlibs.math.random.RandomExt.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of korma-jvm Show documentation
Show all versions of korma-jvm Show documentation
Mathematic library for Multiplatform Kotlin 1.3
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 }
}
}
}