How to pick tickets for uniform frequency?

LuckySam

Member
Dear Forum,

I am working on some new home-brew software.

I have already written the part that can generate a full wheel for any number of balls, any number to play. If it helps to know, the combinations come out in numerical order, e.g. for 5c3:
1) 123
2) 124
3) 125
4) 134
5) 135
...
10) 345

Now I am trying to figure out how to select N tickets from the full wheel, with the requirement that all balls appear with uniform frequency (if possible), or as close as possible (+/-1 from the mean).

My ideal algorithm would work in a loop, e.g.
for n=1:N
Pick the index of the next correct combination, 1-10, from the list above
end
But I don't know if that's possible -- I think probably not.

The algorithm would need to be a general one, not specific to a certain number of balls, so I prefer it to be calculated, rather than table-based for that reason.

Can anyone please direct me to a reference book that would explain such an algorithm? If necessary I can handle the math, but being an engineer I would prefer a cookbook :)

I appreciate your help,

Sam
 

Patrick123

Member
Hi Sam,
As there are many possible combinations,I presume that you'd want a random selection from your full wheel that satisfies your criteria.
One method I'd suggest is as follows:

Code:
x[1...MaxWheel] -> Array of full wheel 
p[1..NumTickets] -> Selection of picks.

for i := 1 to NumTickets do
  p[i] := x[Random(MaxWheel)+1];      // fill initial selection randomly

t := (NumTickets * TicketSize ) div Numballs; // 

Repeat
  Uniform := True;
  p[Random(NumTickets)+1] := x[Random(MaxWheel)+1]; // randomly change one selection
  for a := 1 to BallCount do
    begin
      b := CountBall(a);
      if  (b<t) or (b>t+1) then   // allow for rounding of 1 digit.
        begin
          Uniform := false;
          break;
       end;
   end;
Until Uniform;
I hope this helps
regards
Patrick
 

PAB

Member
Hi LuckySam and welcome to this great Forum :agree: .

This sounds very interesting.
What Programming Language are you using?.
It would be very useful if you posted the code you already have so we can see what exactly is going on. That way, I am sure that one of us on this Forum will be able to help.

All the Bset.
PAB
:wavey:
 

LuckySam

Member
Thanks - more suggestions welcome

Patrick,

Thanks for your suggestion. :thumb: I figured that if I did not get an "elegant" solution, that I would have to "brute force" it. Your approach is much as I might have tried, and you have saved me some time with your psudocode. As it is easy to be misunderstood in a posting, let me make clear that I honor a good "brute force" algorithm that works, I don't consider "brute force" an insult in the absence of elegance.

All,

I'm still open to suggestions, if there is some approach you know that avoids a test-and-discard method.

PAB,

I'm writing in C++, still using VC++6.0. I will post the source for my full-wheel generator function, since others may find it useful (or may know a better way they can share). Can't do that right now -- I'm at work, and the project is at home. As for the rest of the code, it's just too much to post, and mostly GUI anyway. And thanks for your welcome -- this looks like a sharp bunch of people and I knew someone would have a good suggestion.

All the best,

Sam
 

Patrick123

Member
Hi Lucky Sam,
I also racked my brains looking for some method of producing optimised and balanced abbreviated wheels, that's why I finally settled on the test-and-discard method, In fact my generator, does not create the full wheel initially, what I did was specify the numbers range I wanted (1 to 24), I filled the positions randomly, then swapped a random digit on a random ticket, then ran x amount of draws until I got optimised results coming through.
( http://www.onyxsa.co.za/timedesign/LottoWheel.zip )

It's not the most elegant but it gives reasonable results.
Regards
Patrick
 

time*treat

Member
compromise between brute force and static tables

:thumb: Using 5c3 as a basis, you could say (for example) you only want a pair to appear twice in the list. You would check each "candidate" against all previous "accepted" members. So your list becomes:
123, 124, 125, 134, 135, 145, 234, 235, 245, 345

If you save this as a table (in this case the four sets), then, instead of using the numbers as their own value, you might use them as placeholders. That way you can get your "randomness" by mapping a number onto a place.

That way you are not recalculating the optimal set each time, you just "upload" the template and map your random number into place. It seems a bit more cumbersome in the beginning, but it will save you time in the long haul, and is more flexible when you want to make changes.

Now for a monster set like 49C6, you would want to play around with the number of allowed quints, or quads, or even triples to see how this effects the total balance and final number of tickets.
 

MMW

Member
I am so confused

I downloaded the LottoWheel but don't know what to do at this point. Total numbers? Balls (the number of balls within the lottery), Ticket size (number of tickets I want to purchase), Match? #Drawn? #Tickets? Grain? As you can see I am very new to this...can someone please help me:confused:

Thanks,
MMW
 
LuckySam said:
Dear Forum,

I am working on some new home-brew software.

I have already written the part that can generate a full wheel for any number of balls, any number to play. If it helps to know, the combinations come out in numerical order, e.g. for 5c3:
1) 123
2) 124
3) 125
4) 134
5) 135
...
10) 345

Now I am trying to figure out how to select N tickets from the full wheel, with the requirement that all balls appear with uniform frequency (if possible), or as close as possible (+/-1 from the mean).

My ideal algorithm would work in a loop, e.g.
for n=1:N
Pick the index of the next correct combination, 1-10, from the list above
end
But I don't know if that's possible -- I think probably not.

The algorithm would need to be a general one, not specific to a certain number of balls, so I prefer it to be calculated, rather than table-based for that reason.

Can anyone please direct me to a reference book that would explain such an algorithm? If necessary I can handle the math, but being an engineer I would prefer a cookbook :)

I appreciate your help,

Sam


Special cases may require special non-equidistant but stepwise constant distributions. These could be created with this function rww().



Function rww(ParamArray w() As Variant) As Double
'Produces random numbers with defined widths & weights
'06/08/2004 by Bernd Plumhoff. rww expects a vector of n random widths and
'weightings of type double and returns a random number of type double. 'This random number will lie in the given n-width-range of the
'(0,1)-intervall with the given likelihood of the n weightings.
'Examples:
'a) rww(1,0,1,1,8,0) will return a random number between 0.1 and 0.2
'b) rww(5,2,5,1) will return a random number between 0 and 0.5 twice as
' often as a random number between 0.5 and 1.
'c) rww(1/3,0,1/3,1,1/3,0) will return a random number between
' 0.33333333333333 and 0.66666666666666.
'd) rww(5,15.4,3,7.7,2,0) would return a random value between
' 0 and 0.8, first 5 deciles with double likelihood than decile 6-8.

Dim i As Integer
Dim swidths As Double
Dim sw As Double

If (UBound(w) + 1) Mod 2 <> 0 Then
rww = -2 'No even number of arguments: Error
Exit Function
End If

ReDim swidthsi(0 To (UBound(w) + 1) / 2 + 1) As Double
ReDim swi(0 To (UBound(w) + 1) / 2 + 1) As Double
ReDim weights(0 To (UBound(w) + 1) / 2) As Double
ReDim widths(0 To (UBound(w) + 1) / 2) As Double

swidths = 0#
sw = 0#
swi(0) = 0#
swidthsi(0) = 0#
For i = 0 To (UBound(w) - 1) / 2
If w(2 * i) < 0# Then 'A negative width is an error
rww = -3#
Exit Function
End If
widths(i) = w(2 * i)
swidths = swidths + widths(i)
swidthsi(i + 1) = swidths
If w(2 * i + 1) < 0# Then 'A negative weight is an error
rww = -1#
Exit Function
End If
weights(i) = w(2 * i + 1)
If widths(i) > 0# Then
sw = sw + weights(i)
End If
swi(i + 1) = sw
Next i
rww = sw * Rnd
i = (UBound(w) - 1) / 2 + 1 'i already equals (UBound(w) - 1) /
'2 + 1, you may omit this statement.
While rww < swi(i)
i = i - 1
Wend

rww = (swidthsi(i) + (rww - swi(i)) / weights(i) * widths(i)) / swidths

End Function



Suppose you want to simulate teachers who judge pupils. Some teachers do not dare to give extreme grades (assume they give grade 1 for 2% of all cases, grade 2 for 8%, grade 3 for 80%, grade 4 for 8% and grade 5 for 2%). The next teacher is too critical, his distribution is 40%, 30%, 20%, 10% and 0% for grades 1 till 5. Another one only gives grade 4 (60%) and grade 5 (40%). A last one finally offers a “fair” normal distribution (10%, 20%, 40%, 20%, 10%).

How do you produce these random numbers which are distributed as mentioned above? Take the following procedure redw() which creates random numbers with equidistant weights. This function would be called with =INT(1+5*redw(10,20,40,20,10)) to simulate the “fair” teacher, for example.



Option Explicit

Function redw(ParamArray w() As Variant) As Double
' Produces random numbers with equidistant weights
' 06/08/2004 by sulprobil. redw expects a vector of n random
' weightings of type double and returns a random number of type double. This random
' number will lie in the given equidistant n-split-range of the (0,1)-intervall
' with the given likelihood of weightings. Examples:
' a) redw(0,1,0,0,0,0,0,0,0,0) will return a random number between 0.1 and 0.2
' b) redw(2,1) will return a random number between 0 and 0.5 twice as
' often as a random number between 0.5 and 1.
' c) redw(0,1,0) will return a random number between 0.33333333333333 and 0.66666666666666.
' d) redw(15.4,15.4,15.4,15.4,15.4,7.7,7.7,7.7,0,0) would return a random value between
' 0 and 0.8, first 5 deciles with double likelihood than decile 6-8.

Dim i As Integer
Dim sw As Double
ReDim swi(0 To UBound(w) + 2) As Double

sw = 0#
swi(0) = 0#
For i = 0 To UBound(w)
If w(i) < 0# Then 'A negative weight is an error
redw = -1#
Exit Function
End If
sw = sw + w(i) 'Calculate sum of all weights
swi(i + 1) = sw 'Calculate sum of weights till i
Next i

redw = sw * Rnd

i = UBound(w) + 1 ' i already equals UBound(w) + 1, you may omit this statement.
While redw < swi(i)
i = i - 1
Wend

redw = (CDbl(i) + (redw - swi(i)) / w(i)) / (CDbl(UBound(w) + 1))

End Function




Function rand_triang(dMin As Double, dMode As Double, _
dMax As Double) As Double
'Generates a random number, Triang distributed
'[see Vose: Risk Analysis, 2nd ed., p. 128]
'Reverse(moc.LiborPlus.www) 03-May-2007 V0.1
'Similar to @RISK's (C) RiskTriang function.
'rand_triang(minimum,mode,maximum) specifies a triangular
'distribution with three points — a minimum, a mode and
'a maximum. The skew of the triangular distribution is
'driven by the distance of the mode from the minimum and
'from the maximum. Reducing the distance from mode to
'minimum will increase the skew.
Dim dTriangInvMid As Double
Dim dRand As Double, dc_a As Double, db_a As Double
Dim dc_b As Double

Application.Volatile
If dMode <= dMin Or dMax <= dMode Then
rand_triang = CVErr(xlErrNum)
Exit Function
End If
dc_a = dMax - dMin
db_a = dMode - dMin
dc_b = dMax - dMode
'Calculate mid point of value range for cumulative inverse
'function
dTriangInvMid = db_a / dc_a
dRand = Rnd()
If dRand < dTriangInvMid Then
rand_triang = dMin + Sqr(dRand * db_a * dc_a)
Else
rand_triang = dMax - Sqr((1# - dRand) * dc_a * dc_b)
End If
End Function
 
I'm interested in Lotto Wheels and understand the principle of mutations of a number of balls in order to cover an 'area' garanteeing a price if 3 or more numbers drawn are in the wheel.

But can anybody describe in a nutshell how generation of the wheels works (OK I saw some code above but I prefer to know the ideas behind them).
I also would like to know how they behave in reality (do they work well in practise) and also theoretical. Questions like "can you limit the losses to a certain percentage with larger wheels" (hoping for the winning combinations by just luck).
I read about that 163-wheel, where can I find it and how to generate it?
 

Sidebar

Top