Category: |
Fun Stuff |
Author/Contact Info |
OverlordQ - PM Node: 236515 |
Description: |
Takes the results of past lottery drawings and feeds it into a weighted random number generator to guess future results. Horribly inefficient I suspect. |
#!/usr/bin/perl -w
use strict;
use List::Util qw(shuffle);
## CSV file has following format:
## Game Name, Month, Day, Year, Num1, Num2, Num3, Num4, Num5, Mega Bal
+l, Megaplier
## The Megaplier is ignored
open(FILE,"megamillion.csv") or die "Cannot open csv: $!\n";
my @csv = <FILE>;
close(FILE);
## Initialize the temporary hashes
my %hash;
my %bonus;
## Inefficient loop to get number counts
foreach my $line (@csv) {
my ($game,$month,$day,$year,$one,$two,$three,$four,$five,$bonu
+s) = split(/,/,$line);
$hash{$one}++;
$hash{$two}++;
$hash{$three}++;
$hash{$four}++;
$hash{$five}++;
$bonus{$bonus}++;
}
## Initialize the weighted arrays
my @draw;
my @mega;
## Loop and push the numbers into the arrays, and shuffle
foreach my $key (sort keys %hash) {
for(my $count = 0; $count < $hash{$key}; $count++) {
push(@draw,$key);
}
}
@draw = shuffle(@draw);
foreach my $key (sort keys %bonus) {
for(my $count = 0; $count< $hash{$key}; $count++) {
push(@mega,$key);
}
}
@mega = shuffle(@mega);
sub draw_regular {
$draw[ rand(@draw) ];
}
sub draw_mega {
$mega[ rand(@mega) ];
}
## Keep track of number's we've picked
my @picked;
## Loop and draw 5 numbers, pick another incase we draw the same numbe
+r twice.
for(my $i=0;$i<=4;$i++) {
my $number = draw_regular();
foreach my $pick (@picked) {
while($number == $pick) {
$number = draw_regular();
}
}
push(@picked,$number);
}
## Output the Numbers we drew.
print "Draw: " . join(',', sort(@picked)) . "\n";
print "Bonus: " . draw_mega();
|
Re: Lottery Numbers
by jdporter (Paladin) on May 03, 2004 at 01:36 UTC
|
At least your intuition is accurate, wrt the inefficiency of the code. Not that it's all that bad, and for a script like this, who cares if it runs in 3 seconds or 6?
Here's some suggestions:
- Look at all the places you use sort. Most, if not all, are unnecessary.
- Your reading and parsing of the file could be much more concise, with a payoff in efficiency. To wit:
while (<FILE>) { # line at a time
my( $game,$month,$day,$year,$one,$two,$three,$four,$five,$bonus) = s
+plit;
for ( $one,$two,$three,$four,$five ) {
$hash{$_}++;
}
$bonus{$bonus}++; # bonus
}
- Your inner "pushing" loops could be replaced with:
push @draw, ($key) x $hash{$key};
Let perl do the grunt work.
I might even combine the two "pushing" loops into something like the following-
foreach my $key ( keys %hash )
{
push @draw, ($key) x $hash{$key};
push @mega, ($key) x $hash{$key}
if exists $bonus{$key};
}
since, I'm assuming, a number can only appear in the 'bonus' column if it also appears at least once in one of the other columns.
- Your duplicate-detecting loop has a bug. You want to pick a new number if the current number is the same as any in your @picked array. I assume. Right?
If so, then you could use grep to do set membership tests on the array.
Even better would be to use a hash. You're doing many repeated set membership tests on it, and a hash is much better at this than an array. If you care about the order in which numbers are picked (and I assume you do), you could use Tie::IxHash to get an order-preserving hash.
Or in a case like this you could just use an auxiliary "seen" hash.
Here's a solution using grep:
my $number;
do {
$number = draw_regular();
} while ( grep { $_ == $number } @picked );
push @picked, $number;
Here's a solution using an aux hash:
my $number;
do {
$number = draw_regular();
} while ( exists $seen{$number} );
$seen{$number}++;
push @picked, $number;
| [reply] [d/l] [select] |
|
Thanks for the help. The only think you were off on was the bonus. The bonus is an entire diffrent set of numbers not related to the others.
| [reply] |
|
There is one simple thing that you can fix the source file, just delete everything before 10/15/2013.
| [reply] |
Re: Lottery Numbers
by TomDLux (Vicar) on May 04, 2004 at 00:22 UTC
|
You may improve your coding, but the coded won't improve your winnings.
Probabilities are odd, because you're dealing with infinite sequences, and our brains are wired to deal with shorter-term problems ( like our next meal, sex tonight, and the growling noise from the closet ).
Probability says that if you flip a fair coin often enough, and it never balances on the edge, sooner or later you'll have a long string of heads ( or tails ). Once you've had a dozen heads, some people think tails is more likely, because it has to get back to 50-50. That's the trick about infinite sequences. Sooner or later it will get back to balance, but it can take forever to get there. In the meantime, the odds are still 50% heads, 50% tails. Of course, there IS the possibility that a dozen heads indicates an unfair coin.
If you're dealing with one of those lotteries that uses ping-pong balls, there's always the possibility of some accidental inconsistency that makes some numbers fractionally more likely than others. Otherwise, the fact that a number has appeared frequently makes it neither more likely nore less likely to appear in the next draw.
--
TTTATCGGTCGTTATATAGATGTTTGCA
| [reply] |
|
|