2025-07-31 20:50:00 +02:00

109 lines
3.6 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace testdrid
{
public static class RandomExtensions
{
/// <summary>
/// Generates normally distributed numbers. Each operation makes two Gaussians for the price of one, and apparently they can be cached or something for better performance, but who cares.
/// </summary>
/// <param name="r"></param>
/// <param name = "mu">Mean of the distribution</param>
/// <param name = "sigma">Standard deviation</param>
/// <returns></returns>
public static double NextGaussian(this Random r, double mu = 0, double sigma = 1)
{
var u1 = r.NextDouble();
var u2 = r.NextDouble();
var rand_std_normal = Math.Sqrt(-2.0 * Math.Log(u1)) *
Math.Sin(2.0 * Math.PI * u2);
var rand_normal = mu + sigma * rand_std_normal;
return rand_normal;
}
/// <summary>
/// Generates values from a triangular distribution.
/// </summary>
/// <remarks>
/// See http://en.wikipedia.org/wiki/Triangular_distribution for a description of the triangular probability distribution and the algorithm for generating one.
/// </remarks>
/// <param name="r"></param>
/// <param name = "a">Minimum</param>
/// <param name = "b">Maximum</param>
/// <param name = "c">Mode (most frequent value)</param>
/// <returns></returns>
public static double NextTriangular(this Random r, double a, double b, double c)
{
var u = r.NextDouble();
return u < (c - a) / (b - a)
? a + Math.Sqrt(u * (b - a) * (c - a))
: b - Math.Sqrt((1 - u) * (b - a) * (b - c));
}
/// <summary>
/// Equally likely to return true or false. Uses <see cref="Random.Next()"/>.
/// </summary>
/// <returns></returns>
public static bool NextBoolean(this Random r)
{
return r.Next(2) > 0;
}
/// <summary>
/// Shuffles a list in O(n) time by using the Fisher-Yates/Knuth algorithm.
/// </summary>
/// <param name="r"></param>
/// <param name = "list"></param>
public static void Shuffle(this Random r, IList list)
{
for (var i = 0; i < list.Count; i++)
{
var j = r.Next(0, i + 1);
var temp = list[j];
list[j] = list[i];
list[i] = temp;
}
}
/// <summary>
/// Returns n unique random numbers in the range [1, n], inclusive.
/// This is equivalent to getting the first n numbers of some random permutation of the sequential numbers from 1 to max.
/// Runs in O(k^2) time.
/// </summary>
/// <param name="rand"></param>
/// <param name="n">Maximum number possible.</param>
/// <param name="k">How many numbers to return.</param>
/// <returns></returns>
public static int[] Permutation(this Random rand, int n, int k)
{
var result = new List<int>();
var sorted = new SortedSet<int>();
for (var i = 0; i < k; i++)
{
var r = rand.Next(1, n + 1 - i);
foreach (var q in sorted)
if (r >= q)
r++;
result.Add(r);
sorted.Add(r);
}
return result.ToArray();
}
}
}