0

Imagine a list of ordered by descending elements:

List<T> list = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];

How can I implement Random, so that the first elements have a higher chance to be chosen than the other elements? So say like, 20% to get index 1, 17,5% to get index 2, 15% to get index 3, etc. However, the chances shouldn't be that severe, because it needs to add up to 100%. It is also important to note that the list can be of any length, so the chances cannot be hardcoded.

In summary: How can I implement random, so that the index can be chosen of a list of n elements, where the first couple n elements have a higher chance to be chosen than the last couple elements, so by descending order?

Liweinator
  • 57
  • 7
  • "_So say like, 20% to get index 1, ..._", that's the part where you define a function to handle the weight based on index and lenght. and then you slap [weighted random numbers](https://stackoverflow.com/questions/46563490/c-sharp-weighted-random-numbers) on top – Drag and Drop Dec 07 '20 at 13:42

1 Answers1

2

You can use the probability distribution using numeric segments of different sizes.

public sealed class Distribution
{
    public int Index { get; set; }
    public float From { get; set; }
    public float To { get; set; }

    public override string ToString()
    {
        return $"{Index}:{From}-{To}";
    }
}
static void Main(string[] args)
{
    var list = new List<int>()
    {
        10, 9, 8, 7, 6, 5, 4, 3, 2, 1
    };
    var percents = new List<Distribution>();
    var start = 0f;
    var size = 20f;
    var step = 20f/ (list.Count-1);
    for (int j = 0; j < list.Count; j++)
    {
        var distribution = new Distribution()
        {
            Index = j,
            From = start,
            To= start + size,
        };

        percents.Add(distribution);
        start = start + size;
        size -= step;
    }

    var rnd = new Random();
    var frequency = new int[list.Count];
    for (int j = 0; j < 100000; j++)
    {
        var randomValue = rnd.NextDouble() * 100;
        var found = percents.FirstOrDefault(x => x.From <= randomValue && x.To > randomValue);
        frequency[found.Index] = frequency[found.Index] + 1;
    }
    Console.WriteLine(string.Join(System.Environment.NewLine , frequency.Select(x => $"{x}->{((float)x)/1000}%")));
}

Output

Stanislav
  • 459
  • 3
  • 6