How to retrieve k random numbers from an array of unknown size at compile time in VB.NET

1 Answer

0 votes
Imports System

Module Program

    ''' <summary>
    ''' Returns K unique random elements from the specified array.
    '''
    ''' <param name="source">
    ''' The source array. Its size is determined at runtime and does not
    ''' need to be known at compile time.
    ''' </param>
    ''' <param name="k">
    ''' Number of random elements to retrieve.
    ''' </param>
    ''' <returns>
    ''' An array containing K unique randomly selected elements.
    ''' </returns>
    '''
    ''' Explanation:
    ''' ----------------------------
    ''' This function uses a partial Fisher-Yates shuffle:
    '''
    ''' 1. Copy the source array so the original remains unchanged.
    ''' 2. Perform only the first K shuffle iterations.
    ''' 3. After each iteration, one random element is moved into
    '''    its final sampled position.
    ''' 4. The first K elements of the shuffled copy form the sample.
    '''
    ''' Advantages:
    ''' - No duplicate selections.
    ''' - Uniform random distribution.
    ''' - Preserves the original array.
    ''' - Efficient when K is smaller than the array length.
    ''' ----------------------------
    Function GetRandomSample(
        source As Integer(),
        k As Integer) As Integer()

        If source Is Nothing Then
            Throw New ArgumentNullException(NameOf(source))
        End If

        If k < 0 OrElse k > source.Length Then
            Throw New ArgumentOutOfRangeException(
                NameOf(k),
                "K must be between 0 and the number of elements.")
        End If

        ' Create a copy so the source array is not modified.
        Dim workingCopy As Integer() =
            CType(source.Clone(), Integer())

        Dim rng As New Random()

        ' Partial Fisher-Yates shuffle.
        For i As Integer = 0 To k - 1

            Dim randomIndex As Integer =
                rng.Next(i, workingCopy.Length)

            Dim temp As Integer = workingCopy(i)
            workingCopy(i) = workingCopy(randomIndex)
            workingCopy(randomIndex) = temp
        Next

        ' Copy the first K sampled elements.
        Dim result(k - 1) As Integer

        Array.Copy(
            workingCopy,
            0,
            result,
            0,
            k)

        Return result
    End Function

    Sub Main()

        Try

            ' Array size is only known at runtime.
            Dim numbers() As Integer =
            {
                10, 20, 30, 40, 50,
                60, 70, 80, 90, 100
            }

            Dim k As Integer = 4

            Dim sample() As Integer =
                GetRandomSample(numbers, k)

            Console.WriteLine("Original Array:")
            Console.WriteLine(String.Join(", ", numbers))

            Console.WriteLine()
            Console.WriteLine($"Random Sample ({k} elements):")
            Console.WriteLine(String.Join(", ", sample))

        Catch ex As Exception

            Console.WriteLine($"Error: {ex.Message}")

        End Try

    End Sub

End Module
                 
                     
'
' run:
'
' Original Array:
' 10, 20, 30, 40, 50, 60, 70, 80, 90, 100
' 
' Random Sample (4 elements):
' 50, 40, 80, 30
' 
'

 



answered Oct 2 by avibootz

Related questions

...