Lottery number generator (duplication protection)
Post by michael on Mar 28th, 2016, 11:25am
**SPECIAL NOTE: This is not the original post.. I have removed the old program and replaced it with a much more advanced version with special tools.
This is the Canadian LOTTO MAX.. there are 7 numbers out of 49 that you must pick.
This program should be up to everyones standards.
1) no use of GOTO or GOSUB
2) no ancient coding ways.
3) it was built from the ground up
4) it has key detection so you can roll for more numbers
5) The most impressive part (Procedure array value duplication protection)
(sounds impressive eh?)
Please let me know if it isn't perfect.. I have been testing this and perfecting it for hours..
Code:
DIM x%(7)
CLS:PROC_newnumbers
REPEAT
key$=""
key$ =INKEY$(1)
IF LEN(key$) = 1 THEN
IF key$="r" OR key$="R" THEN PROC_newnumbers
ENDIF
UNTIL key$="q" OR key$="Q"
PRINT "done"
END
DEF PROC_newnumbers
CLS
PRINT "Here is 7 numbers for Lotto Max"
REPEAT
FOR t=1 TO 7
x%(t)=RND(49)
NEXT t
PROC_comparray(7)
UNTIL cond$="cleared"
FOR t=1 TO 7
PRINT x%(t)
NEXT t
PRINT "Press R or r for more numbers or Press Q or q to quit"
ENDPROC
DEF PROC_comparray(n)
cond$="cleared"
nex=1
FOR cou=1 TO n
FOR co=nex TO n
IF cou<>co THEN IF x%(cou)=x%(co) THEN cond$="duplicate"
NEXT co
nex=nex+1
NEXT cou
ENDPROC
Re: Lottery number generator (LOTTO MAX Canada)
Post by Zaphod on Mar 28th, 2016, 1:24pm
Reinventing the wheel, yes indeed.
The BB4W wiki has a much more elegant solution by Richard in this
http://bb4w.wikispaces.com/Notes+on+the+use+of+RND
Opinion!
A beginner would be much better off adopting the kind of style used in the Wiki and supplied code examples rather than using the archaic Gosub an Goto of the very early basics. These constructs were dropped from common use 30 years or more ago. It is not that they are wrong just that better and faster constructs are now available in all modern dialects of BASIC.
Re: Lottery number generator (LOTTO MAX Canada)
Post by michael on Mar 28th, 2016, 2:22pm
Thanks.. I will try to make better structured programs.
I do program much the same as I did on the Trs-80 (1982).. (but I sometimes program like this because I am not putting any effort into making it slim)
I just do what ever works.
My use of RND comes from the help section.
It more accurately represents the old basics in the way I have presented.
My programming habits haven't changed much since I programmed from 1982- 1990 (approximately) and then for a very short bit in 2009 and then from March 2015- now..
Old habits die hard. When BBC Basic was being released, I
would have been only 8 years old. (if it is 35 years old)
I see this is the simpler method of making a similar program (Lotto Max uses 7 numbers not 6.. ( I got this from your link)
I actually use for/next loops in my programs a lot.
But for some reason I just did it the way I did...
(AND actually this is a translation from a program I made in APRIL 11, 2015.. ) So its just that.. I am more advanced than this..
And when I try to remake the board game I made back in 1988, we will see how that goes.. Because I am going to try to make it have artificial intelligence (to a degree) instead of a player against themselves style.
Re: Lottery number generator (LOTTO MAX Canada)
Post by TheFamousCash on Mar 28th, 2016, 11:17pm
On the other hand, why use random numbers? Surely you understand chances are worthless?
Why not use semi-random?
The best National lottery program shows TWO jackpot hits since lottery began.
See list of other hits.
http://www.ebay.co.uk/itm/111940737683?ssPageName=STRK:MESELX:IT&_trksid=p3984.m1555.l2649
Re: Lottery number generator (duplication protecti
Post by Zaphod on Mar 29th, 2016, 1:24pm
We all seek perfection but in software that is very difficult to define.
Your code revision is much better though. You can change. Remember, I'm pulling for you. We're all in this together.
I would suggest some modifications in terms of style and making the program and modules not so specific. The you can then reuse the code elsewhere, which might stop you reinventing the wheel but does save time. I make no claims of it being even close to perfect.
Here are the specifics.
First the logic is unchanged!
Procedure names starting with an underscore are reserved for library functions by BB4W convention so those are changed.
Where a Procedure is just determining a value, especially a Boolean then a function is probably a better choice.
Where variables are only used within a Procedure or Function then they are made Local.
To make the Procedures and Functions modular the data are passed to them as parameters.
The limits of arrays passed are tested so there are no errors.
The variable naming conventions are in line with the recommendations for BB4W and will show no warnings in the Cross Reference Utility.
Non functioning lines were removed.
Code: Numbers%=7
Limit%=49
DIM X%(Numbers%)
CLS
PROCnewnumbers(X%(),Limit%)
REPEAT
Key$ =INKEY$(1)
IF Key$="r" OR Key$="R" THEN CLS:PROCnewnumbers(X%(),Limit%)
UNTIL Key$="q" OR Key$="Q"
PRINT "done"
END
DEF PROCnewnumbers(n%(), max%)
LOCAL t
PRINT "Here are "+STR$Numbers%+" non-repeating numbers for a Lottery in the range 1 to "+STR$max%
REPEAT
FOR t=1 TO DIM(n%(),1)
n%(t)=RND(max%)
NEXT
UNTIL NOT FNcomparray(n%())
FOR t=1 TO DIM(n%(),1)
PRINT n%(t)
NEXT
PRINT "Press R or r for more numbers or Press Q or q to quit"
ENDPROC
DEF FNcomparray(a%())
LOCAL dupe%, nex, cou, co
nex=1
FOR cou=1 TO DIM(a%(),1)
FOR co=nex TO DIM(a%(),1)
IF cou<>co THEN IF a%(cou)=a%(co) THEN dupe%=TRUE
NEXT
nex+=1
NEXT
=dupe%
The comments made by others about why you would want random numbers is of course valid, and certainly Richard's routine referenced earlier in this conversation is far more efficient.
In terms of lotteries you can improve your chances of being amongst a smaller number of winners by choosing less popular numbers. The popularity of numbers is pretty easy to find.
Good Luck.
Re: Lottery number generator (duplication protecti
Post by hellomike on Apr 3rd, 2016, 4:25pm
Hi Michael,
For your PROC_comparray() code, Zaphod already made some good modifications. I.e. making it a function and array-name/size independent.
However I like to make some other comments and I made a little program around it to make you see the differences.
Here is the code. It has line numbers just so I/we can refer to specific lines when discussing.
Code: 10 SIZE%=5000
20 DIM A%(SIZE%-1)
30 FOR I%=0 TO SIZE%-1:A%(I%)=I%:NEXT
40
50 T%=TIME:PRINT FNcomparray(A%()) TIME-T%
60 T%=TIME:PRINT FNcomparrayNEW(A%()) TIME-T%
70
80 PRINT
90
100 A%(SIZE%/2)=1
110 T%=TIME:PRINT FNcomparray(A%()) TIME-T%
120 T%=TIME:PRINT FNcomparrayNEW(A%()) TIME-T%
130 END
140
150 DEF FNcomparray(a%())
160 LOCAL dupe%, nex, cou, co
170 nex=1
180 FOR cou=1 TO DIM(a%(),1)
190 FOR co=nex TO DIM(a%(),1)
200 IF cou<>co THEN IF a%(cou)=a%(co) THEN dupe%=TRUE
210 NEXT
220 nex+=1
230 NEXT
240 =dupe%
250
260 DEF FNcomparrayNEW(a%())
270 LOCAL cou, co
280 FOR cou=0 TO DIM(a%(),1)-1
290 FOR co=cou+1 TO DIM(a%(),1)
300 IF a%(cou)=a%(co) THEN =TRUE
310 NEXT
320 NEXT
330 =FALSE
First your approach has a bug in it, because the loops start with 1 and not zero. The (0) element of the array is not checked. You can see it failing when you alter line 100 into:
Code:
making A%(2500) equal to A%(0).
FNcomparray() will not signal a duplicate.
Then about the use of variable 'nex'. Note that it always has the same value as the variable 'cou'. I recommend you to remove 'nex' and simply use 'cou' instead.
Furthermore if you start the inner loop with 'cou+1' then you never have to check later if cou<>co because it always is, so you can remove that condition too.
Of course when doing this, make sure that the outer loop end value is 'DIM(a%(),1)-1' otherwise 'co' will eventually become 1 bigger than the last array index and you face a "Bad subscript at line 300".
Finally it is recommended that you leave the function (or PROCedure) as soon as a duplicate value is found. This gives huge performance boost.
For example if array element 0 and 1 are equal, then 'a%(cou)=a%(co)' is true in the very first iteration of both loops, where cou=0 and co=cou+1. There is no need to continue anymore.
This is especially important for code like comparing which uses loops within loops.
Running the program will execute both functions when the A%() array has no duplicate values so '0' is returned both times.
It will then execute both functions again with element a%(1) and A%(2500) being equal so '-1' is returned both times.
The return values are followed by the time in centi second that the execution of that specific call took.
On my system, this was the output:
Code: 0 1115
0 713
-1 1112
-1 0
Note the time difference when both loops are executed fully (11.15 sec vs 7.13 sec) because there are no equals in the array but especially note, the difference when element 1 and 2500 are equal (11.12 sec vs 0.00 sec).
I hope you find the tips welcome Michael. Feel free to comment on it further.
Regards,
Mike
Re: Lottery number generator (duplication protecti
Post by Wildmooer on Apr 24th, 2016, 3:37pm
I'm new to this, but I like it!
Please comment on this alternate method:
Code:
n=0:key$="":spot=0
REPEAT
all$=""
FOR n=1 TO 49
all$=all$+CHR$(n)
NEXT n
CLS
PRINT "Here are 7 numbers for Canadian Lotto Max:"
FOR n=1 TO 7
spot=RND(LEN(all$))
PRINT ASC(MID$(all$,spot,1))
all$=LEFT$(all$,spot-1)+MID$(all$,spot+1)
NEXT n
PRINT "Press [ANY KEY] for More Numbers or"
PRINT "Press [Q] or [q] to Quit"
REPEAT
key$=INKEY$(0)
UNTIL key$<>""
UNTIL key$="q" OR key$="Q"
PRINT "done"
END
Re: Lottery number generator (duplication protecti
Post by Zaphod on Apr 24th, 2016, 3:55pm
I like that a lot as a technique!
Simple and effective.
But please don't do this:
Code:
REPEAT
key$=INKEY$(0)
UNTIL key$<>""
You need a time delay so the cpu is not in a tight loop. INKEY$(1) will do that just fine.
For someone who is 'new to this' it's a great start and I can't wait to see what you do when you get more time in on BB4W.
Re: Lottery number generator (duplication protecti
Post by Wildmooer on Apr 25th, 2016, 03:56am
Thank you for the tip!!!