First, I made a little structure to hold the digits and the weight percent.
Structure Weights
Public Sub New(num As Integer, per As Integer)
Number = num
Percent = per
End Sub
Public Number As Integer
Public Percent As Integer
End Structure
Then I filled a list of the structure. Next I looped through the lstWeights and added digits to a second list; adding each digit to the lst x number of times based on the percent weight.
Private Sub BuildWeightedList()
lstWeights.Add(New Weights(10, 2))
lstWeights.Add(New Weights(9, 4))
lstWeights.Add(New Weights(8, 5))
lstWeights.Add(New Weights(7, 8))
lstWeights.Add(New Weights(6, 9))
lstWeights.Add(New Weights(5, 11))
lstWeights.Add(New Weights(4, 13))
lstWeights.Add(New Weights(3, 14))
lstWeights.Add(New Weights(2, 16))
lstWeights.Add(New Weights(1, 18))
'Add digits to lst; each digit is added as many times as it weight
For Each item As Weights In lstWeights
For x As Integer = 1 To item.Percent
lst.Add(item.Number)
Next
Next
End Sub
Now to get the random weighted digits (1-10) Remember there are 18 ones, a16 twos, 14 threes etc. Generate a random index and get the digit at that index. For testing purposes, I added the result to yet another list.
Private Sub WeightedRandom()
Dim ListCount As Integer = lst.Count
Dim index As Integer = R1.Next(0, ListCount)
Dim d1result1 As Integer = lst(index)
lstResult.Add(d1result1)
End Sub
Classes level variables:
Private lstWeights As New List(Of Weights)
Private lst As New List(Of Integer)
Private lstResult As New List(Of Integer)
Private R1 As New Random
In the form load build the first list. lstWeights
BuildWeightedList()
Call the procedure from a button.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For x = 0 To 10000
WeightedRandom()
Next
TestWeighted()
MessageBox.Show("Done")
End Sub
Then I tested thusly:
Private Sub TestWeighted()
Dim c10, c9, c8, c7, c6, c5, c4, c3, c2, c1 As Integer
For Each x As Integer In lstResult
Select Case x
Case 1
c1 += 1
Case 2
c2 += 1
Case 3
c3 += 1
Case 4
c4 += 1
Case 5
c5 += 1
Case 6
c6 += 1
Case 7
c7 += 1
Case 8
c8 += 1
Case 9
c9 += 1
Case 10
c10 += 1
End Select
Next
Dim divisor As Integer = lstResult.Count
Debug.Print($"1 is {c1 / divisor:P00}, 2 is {c2 / divisor:P00}, 3 is {c3 / divisor:P00}, 4 is {c4 / divisor:P00}, 5 is {c5 / divisor:P00}, 6 is {c6 / divisor:P00}, 7 is {c7 / divisor:P00}, 8 is {c8 / divisor:P00}, 9 is {c9 / divisor:P00}, 10 is {c10 / divisor:P00},")
End Sub
The result in the immediate window:
1 is 18%, 2 is 17%, 3 is 13%, 4 is 13%, 5 is 11%, 6 is 9%, 7 is 8%, 8 is 5%, 9 is 4%, 10 is 2%,
then to test John's extension
Private Sub Testjmcilhinney()
Dim R1 As New Random 'CORRECTION - moved this to class level
'Dim weightings = {100, 90, 80, 70, 60, 50, 40, 30, 20, 10}
'Took the weights provided by the OP and divided by 550 (total of his percentages) to get weightings totaling 100
Dim weightings = {18, 16, 14, 13, 11, 9, 8, 5, 4, 2} 'Totals 100%
Dim d1result1 As Integer = R1.NextWithWeighting(1, 11, weightings)
lstResult.Add(d1result1)
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For x = 0 To 10000
Testjmcilhinney()
Next
TestWeighted()
MessageBox.Show("Done")
End Sub
result in immediate window
1 is 60%, 2 is 0%, 3 is 21%, 4 is 0%, 5 is 0%, 6 is 19%, 7 is 0%, 8 is 0%, 9 is 0%, 10 is 0%,
second try
1 is 0%, 2 is 0%, 3 is 0%, 4 is 53%, 5 is 0%, 6 is 3%, 7 is 0%, 8 is 44%, 9 is 0%, 10 is 0%,
I am obviously doing something very wrong.
After correction (see comment)
1 is 19%, 2 is 17%, 3 is 14%, 4 is 13%, 5 is 11%, 6 is 9%, 7 is 9%, 8 is 4%, 9 is 4%, 10 is 1%,