Skip to content

Instantly share code, notes, and snippets.

@retraigo
Last active September 21, 2022 16:08
Show Gist options
  • Save retraigo/51c3c2d0d288c0b4a1a692d720282fd0 to your computer and use it in GitHub Desktop.
Save retraigo/51c3c2d0d288c0b4a1a692d720282fd0 to your computer and use it in GitHub Desktop.
// Weighted random selection in Scala 2
// You have an array of items. Each item is an unsigned integer.
// The value of each item determines its weight.
// Higher the weight, higher the chance of rolling it.
class Fortuna(items: Array[Double]) {
private val weights = items;
private val cumulativeWeights: Array[Double] = new Array(items.length);
private var totalChance: Double = 0;
for (i <- 0 until items.length) {
cumulativeWeights(i) = totalChance + items(i);
totalChance = totalChance + items(i);
}
def get(count: Int): Array[Int] = {
val result = new Array[Int](count);
for (i <- 0 until count) {
result(i) = roll();
}
return result;
}
def get_with_linear_search(count: Int): Array[Int] = {
val result = new Array[Int](count);
for (i <- 0 until count) {
result(i) = roll_with_linear_search();
}
return result;
}
def roll(): Int = {
if (cumulativeWeights.length == 1) return -1;
val rng = Math.random() * totalChance;
var lower = 0;
var max = cumulativeWeights.length - 1;
var mid = ((max + lower) / 2);
while (mid != 0 && lower <= max) {
if (
(cumulativeWeights(mid) > rng &&
cumulativeWeights(mid - 1) < rng) ||
cumulativeWeights(mid) == rng
) return mid;
if (cumulativeWeights(mid) < rng) {
lower = mid + 1;
mid = ((max + lower) / 2);
} else {
max = mid - 1;
mid = ((max + lower) / 2);
}
}
return mid;
}
def roll_with_linear_search(): Int = {
if (weights.length == 1) return -1;
val rng = Math.random() * totalChance;
var total = totalChance;
var i = 0;
if (totalChance == 0) {
while (i < weights.length) {
total = total + weights(i);
i = i + 1;
}
}
val result = Math.random() * total;
var going = 0.0;
i = 0;
while (i < weights.length) {
going = going + weights(i);
if (result < going) {
return i;
}
i = i + 1;
}
return (Math.random() * weights.length).toInt;
}
}
object Test {
val data: Array[Double] = Array(25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 11,
11, 11, 25, 25, 25, 11, 1, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 11, 11, 11, 25, 25, 25, 11, 25, 1, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 11, 11, 11, 11, 11, 11, 11, 11, 1, 1, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 11, 11, 11, 11, 11, 11, 11,
25, 25, 1, 1, 1, 1, 1, 1, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 11, 11,
11, 25, 25, 11, 11, 25, 11, 1, 1, 1, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 11,
11, 25, 1, 1, 1, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 1, 1, 25, 25, 25, 25, 1, 1, 1, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25,
25, 25, 25, 1, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, 25);
def main(args: Array[String]) = {
println("Woke");
val machine = new Fortuna(data);
println(s"${machine.get(1000).toSeq}")
println(s"${machine.get_with_linear_search(1000).toSeq}")
}
}
// Weighted random selection in Scala 3
// You have an array of items. Each item is an unsigned integer.
// The value of each item determines its weight.
// Higher the weight, higher the chance of rolling it.
class Fortuna(items: Array[Double]) {
private val weights = items;
private val cumulativeWeights: Array[Double] = new Array(items.length);
private var totalChance: Double = 0;
for (i <- 0 until items.length) {
cumulativeWeights(i) = totalChance + items(i);
totalChance = totalChance + items(i);
}
def get(count: Int): Array[Int] =
val result = new Array[Int](count);
for (i <- 0 until count) {
result(i) = roll();
}
return result;
def get_with_linear_search(count: Int): Array[Int] =
val result = new Array[Int](count);
for (i <- 0 until count) {
result(i) = roll_with_linear_search();
}
return result;
def roll(): Int =
if (cumulativeWeights.length == 1) return -1;
val rng = Math.random() * totalChance;
var lower = 0;
var max = cumulativeWeights.length - 1;
var mid = ((max + lower) / 2);
while (
mid != 0 && lower <= max
) {
if (
(cumulativeWeights(mid) > rng &&
cumulativeWeights(mid - 1) < rng) ||
cumulativeWeights(mid) == rng
) return mid;
if (cumulativeWeights(mid) < rng) {
lower = mid + 1;
mid = ((max + lower) / 2);
} else {
max = mid - 1;
mid = ((max + lower) / 2);
}
}
return mid;
def roll_with_linear_search(): Int =
if (weights.length == 1) return -1;
val rng = Math.random() * totalChance;
var total = totalChance;
var i = 0;
if (totalChance == 0) {
while (i < weights.length) {
total = total + weights(i);
i = i + 1;
}
}
val result = Math.random() * total;
var going = 0.0;
i = 0;
while (i < weights.length) {
going = going + weights(i);
if (result < going) {
return i;
}
i = i + 1;
}
return (Math.random() * weights.length).toInt;
}
val data: Array[Double] = Array(25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,11,11,11,25,25,25,11,1,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,11,11,11,25,25,25,11,25,1,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,11,11,11,11,11,11,11,11,1,1,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,11,11,11,11,11,11,11,25,25,1,1,1,1,1,1,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,11,11,11,25,25,11,11,25,11,1,1,1,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,11,11,25,1,1,1,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,1,1,25,25,25,25,1,1,1,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,1,25,25,25,25,25,25,25,25,25,25,25,25);
@main def Test() =
val machine = new Fortuna(data);
println(s"${machine.get(1000).toSeq}")
println(s"${machine.get_with_linear_search(1000).toSeq}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment