(Let's keep our discussion on the list, so we can all help and learn.)

On Feb 27, 2004, at 9:28 AM, Cy Kurtz wrote:

Here is my updated code, in case you're interested. It's not as elegant
as your code(I can see I have a lot to learn!), but it works for me. I'm
still studying your code. Thank you for all your help.

This version is MUCH better, I think. Keep at it! I'll provide some more general comments below...


#!/usr/bin/perl
#spick.pl
#a program to pick lottery numbers
#select 50 numbers in 10 5 number tickets
#select 10 supernumbers
#all numbers range from 1 to 52
#select each number only once
#select each super number only once
use strict;
use warnings;
my $try;
my @numbers;
my @supers;
my $i;
my $j;

You can eliminate both of the above lines by adding a my into your for loops as I'll show below.


my $k;
print "\n\n";
for $i(1..10){

for my $i (1..10) {


for $j(1..5){

for my $j (1..5) {


$try=int(rand(51)+.5)+1;

Don't do that. rand() returns a number between 0 and what you give as an argument. Just shave the decimal and add one.


$try = int(rand 51) + 1;

                $k=1;
                while($k<(($i-1)*5+$j)){

Pop quiz time. What's easier to read, the above or this:


while( $k < ( ( $i - 1 ) * 5 + $j ) ) {

We won't bill you for the whitespace. ;)

                        if($try != $numbers[$k]){#good number
                                $k=$k+1;
                        }
                        else {#duplicate
                                $try=int(rand(51)+.5)+1;
                                $k=1;
                        }
                }
                $numbers[(($i-1)*5)+$j]=$try;#store number
                if($numbers[($i-1)*5+$j]<10){print "0";}
                print $numbers[(($i-1)*5)+$j],"  ";

This whole section above is "busy work". We try to avoid that in Perl and just get things done. I know that's not the best explanation, but it's hard for me to put into words.


Let me try a fresh tactic. I'm going to put another rewrite in here. But this time, I've tried to mirror how I would do exactly what you are doing, minus the busy work. ;) I also don't use a module this time, so it's maybe a little easier to follow. Don't let the length scare you, it's mostly comments. See if this gives you some fresh perspective:

#!/usr/bin/perl

use strict;
use warnings;

# a hash cannot have two identical keys, so it makes a handy choice
# for the problem we are trying to solve, even if we are building a
# list that feels more like an array
my(%numbers, %powerballs);

print "\n\n";
# I'm using identical loops; do note my variable names though as I
# think they tell us a little more about what's really going on
for my $ticket (1..10) {
        for my $number (1..5) {
                # See how I declare this right where I need it?
                # That means I don't have to remember where some variable that
                # just shows up again came from.  It's self documenting.
                # Others will disagree, but it makes the most sense to me.
                my $new;
                # The next line is where all the magic is.  It's a little
                # tricky, but it's a common Perl tactic worth learning.
                # Let's take it piece by piece.  It's just a loop, and what
                # it does is almost as basic.  It puts random numbers in $new
                # until we find one we haven't used before.  We check that
                # with the hash and that's the tricky part.
                # ... while $numbers{$new}++;
                # We use $new as a key for the hash, and add one to the
                # linked value after we check what that value was.
                # The first time we see a value it will be 0 or false,
                # ending the loop.  Future tests of the number will be higher
                # and thus true, causing the loop to try again.
                do { $new = int(rand 51) + 1 } while $numbers{$new}++;
                printf '%02d  ', $new;
        }       # end block, $number and $new cease to exist here

        my $new;        # a different $new
        do { $new = int(rand 51) + 1 } while $powerballs{$new}++; # same trick
        printf "-  %02d\n", $new;
}       # end block, $ticket and $new cease to exist here
print "\n\n";

__END__

Hope that helps.

Please note that I'm not knocking your code. You have a working program and that's all you really need. I'm just trying to guide you towards simplification, to make things easier to read and follow. It'll also save you time, with future projects.

James


-- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] <http://learn.perl.org/> <http://learn.perl.org/first-response>




Reply via email to