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 { /// /// 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. /// /// /// Mean of the distribution /// Standard deviation /// 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; } /// /// Generates values from a triangular distribution. /// /// /// See http://en.wikipedia.org/wiki/Triangular_distribution for a description of the triangular probability distribution and the algorithm for generating one. /// /// /// Minimum /// Maximum /// Mode (most frequent value) /// 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)); } /// /// Equally likely to return true or false. Uses . /// /// public static bool NextBoolean(this Random r) { return r.Next(2) > 0; } /// /// Shuffles a list in O(n) time by using the Fisher-Yates/Knuth algorithm. /// /// /// 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; } } /// /// 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. /// /// /// Maximum number possible. /// How many numbers to return. /// public static int[] Permutation(this Random rand, int n, int k) { var result = new List(); var sorted = new SortedSet(); 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(); } } }