using System; using System.Collections.Generic; using System.Linq; namespace MLEM.Extensions { /// /// A set of extensions for dealing with /// public static class RandomExtensions { /// /// Gets a random entry from the given collection with uniform chance. /// /// The random /// The entries to choose from /// The entries' type /// A random entry public static T GetRandomEntry(this Random random, ICollection entries) { // ElementAt internally optimizes for IList access so we don't have to here return entries.ElementAt(random.Next(entries.Count)); } /// /// Returns a random entry from the given collection based on the specified weight function. /// A higher weight for an entry increases its likeliness of being picked. /// /// The random /// The entries to choose from /// A function that applies weight to each entry /// The entries' type /// A random entry, based on the entries' weight /// If the weight function returns different weights for the same entry public static T GetRandomWeightedEntry(this Random random, ICollection entries, Func weightFunc) { var totalWeight = entries.Sum(weightFunc); var goalWeight = random.Next(totalWeight); var currWeight = 0; foreach (var entry in entries) { currWeight += weightFunc(entry); if (currWeight > goalWeight) return entry; } throw new IndexOutOfRangeException(); } /// public static T GetRandomWeightedEntry(this Random random, ICollection entries, Func weightFunc) { var totalWeight = entries.Sum(weightFunc); var goalWeight = random.NextDouble() * totalWeight; var currWeight = 0F; foreach (var entry in entries) { currWeight += weightFunc(entry); if (currWeight > goalWeight) return entry; } throw new IndexOutOfRangeException(); } /// /// Returns a random floating-point number that is greater than or equal to 0, and less than . /// /// The random. /// The (exclusive) maximum value. /// A single-precision floating point number that is greater than or equal to 0, and less than . public static float NextSingle(this Random random, float maxValue) { return maxValue * random.NextSingle(); } /// /// Returns a random floating-point number that is greater than or equal to , and less than . /// /// The random. /// The (inclusive) minimum value. /// The (exclusive) maximum value. /// A single-precision floating point number that is greater than or equal to , and less than . public static float NextSingle(this Random random, float minValue, float maxValue) { return (maxValue - minValue) * random.NextSingle() + minValue; } #if !NET6_0_OR_GREATER /// /// Returns a random floating-point number that is greater than or equal to 0, and less than 1. /// /// The random. /// A single-precision floating point number that is greater than or equal to 0, and less than 1. public static float NextSingle(this Random random) { return (float) random.NextDouble(); } #endif } }