Как создать генератор случайных чисел, который увеличит вероятность того, что числа еще не были возвращены? - PullRequest
0 голосов
/ 13 апреля 2020

Я бы хотел генератор случайных чисел, который будет возвращать целые числа в диапазоне, так что самые последние возвращенные числа будут иметь вероятность наименьшего , а те, которые были возвращены наименьшим будет иметь наибольшую вероятность быть возвращенной следующей.

У меня есть наивная реализация в C# (ниже), которая в основном просто имеет счетчик для каждого числа в диапазоне и увеличивает этот счетчик каждый раз, когда номер не был выбран и сбрасывает счетчик на 1 для выбранного номера. Вероятность каждого числа рассчитывается путем деления его счетчика на сумму всех счетчиков.

Это работает так, как мне бы хотелось, но мне интересно, есть ли версия этого умного человека или Формальное распределение вероятностной статистики или лучший трюк.

Спасибо за любую помощь!

using System.Collections.Generic;
using System.Linq;
using System;

/// <summary>
/// Returns a random number from 0 to n (referred to as options). The most recently returned options will have 
/// the least likelyhood of being returned next.
/// </summary>
public class IncreasingProbabilitySet
{
    private List<int> options = new List<int>();
    private readonly Random random = new Random();

    public IncreasingProbabilitySet(int numOptions)
    {
        for (var i = 0; i < numOptions; i++)
        {
            options.Add(1);
        }
    }

    /// <summary>
    /// Gets a random number according to the current probability of each of the options, resets the probability of 
    /// the option that was given, and raises the probability of the rest of the options.
    /// </summary>
    /// <returns>The randomly chosen option.</returns>
    public int GetOption()
    {
        int option = -1;
        int sum = options.Sum();
        int hit = this.random.Next(sum) + 1;
        int runningTotal = 0;
        for (var i = 0; i < options.Count; i++)
        {
            runningTotal += options[i];

            if (hit <= runningTotal)
            {
                option = i;
                break;
            }
        }

        for (var i = 0; i < options.Count; i++)
        {
            if (i != option) options[i]++;
            else options[i] = 1;
        }

        return option;
    }

    /// <summary>
    /// Resets the current probabilities of the options.
    /// </summary>
    public void Reset()
    {
        for(var i = 0; i < options.Count; i++)
        {
            options[i] = 1;
        }
    }
}

...