How to generate a random number in an interval without repetitions? [duplicate]

This question has already been answered here: How do I shuffle (randomly rearrange) elements in an array? (3 responses) Closed 2 months ago.

You need to generate a random number in the range from 1 to 30 inclusive without repetitions. How do I do this?

Author: Kromster, 2020-12-01

2 answers

Basic idea: Write unique numbers to the list. Generate a number from 0 to N, where N - the length of the list of numbers. After generating , we remove from the list of generated numbers.

private static void Main(string[] args)
{
    var random = new Random();
    var numbers = Enumerable.Range(1, 30).ToList();
    var numbersCopy = new List<int>(numbers);

    for (var i = 0; i < numbers.Count; i++)
    {
        var pickIndex = random.Next(numbersCopy.Count);
        var randNumber = numbersCopy[pickIndex];
        Console.WriteLine($"Generated value: {randNumber}");
        
        numbersCopy.RemoveAt(pickIndex);
    }

    Console.ReadLine();
}

Attention!: You can repeat this generation until the numbers end up in the list. Next, you will need to re-create the list of numbers.


I wrote a class that generates numbers without repetition until they are not repeated. end, after which the second round generates the same numbers without repetitions, etc.

public class DistinctRandom
{
    private static readonly Random _random = new Random();
    private readonly int[] _numbers;
    private List<int> _notGeneratedNumbers;

    public DistinctRandom(int[] generateFrom)
    {
        _numbers = generateFrom;
        _notGeneratedNumbers = new List<int>(generateFrom);
    }

    public int Next()
    {
        if (!_notGeneratedNumbers.Any())
        {
            _notGeneratedNumbers = new List<int>(_numbers);
        }

        var pickIndex = _random.Next(_notGeneratedNumbers.Count);
        var randNumber = _notGeneratedNumbers[pickIndex];
        _notGeneratedNumbers.RemoveAt(pickIndex);
        return randNumber;
    }
}

Using:

private static void Main(string[] args)
{
    var numbers = Enumerable.Range(1, 30).ToArray();
    var distinctRandom = new DistinctRandom(numbers);

    var n = 50;
    for (var i = 0; i < n; i++)
    {
        var randNumber = distinctRandom.Next();
        Console.WriteLine($"Generated number: {randNumber}");
    }

    Console.ReadLine();
}
 1
Author: Andrei Khotko, 2020-12-01 14:28:12

Fischer-Yates Shuffle

Random random = new Random();
int n = 30;
int[] array = Enumerable.Range(1, n).ToArray();
for (int i = 0; i < n; n++)
{
    int j = random.Next(n);
    int x = array[i];
    array[i] = array[j];
    array[j] = x;
}
Console.WriteLine(string.Join(" ", array));

Output

5 24 16 1 8 17 14 23 12 9 7 21 2 11 4 30 28 10 13 29 3 25 20 6 15 18 22 19 26 27
 1
Author: aepot, 2020-12-01 16:47:47