in reply to Newbie Question on pushing Arrays

A bit of advice every newbie gets: put use strict as the first line of code in your script and add -w to the #! line *always* (the latter can be done away with after you've finished developing and testing the code). Doing so will force you to declare your variables and think hard about the scope of your variables (and catch typos -- $zahl is undeclared in this code). Basically, this will force you to declare your variables before you use them (use the my operator, which is documented in perldoc -f my)

One minor problem here is that $limit is, as written, going to contain the newline the user has to enter. Use chomp $limit; on the next line to remove that newline.

Now, onto the logic of your loop. I think it's more naturally written as a for loop, with 3 as the lower bound (you already know 2 is prime, after all) and $limit as the upper bound, incrementing by one each time. That way you don't have to fiddle with incrementing $number on both branches (whether it's prime or not). The code for that loop then looks like this:

for (my $number = 3; $number < $limit; $number++) { #stuff }

I like your use of a flag, keep that! But maybe rename it, like $isprime, which is more descriptive =)

As for the inner loop, you want to break out of it once you've found a member of @primes that evenly divides $number ... so use the last operator to do that. I'm not sure the array's getting mixed up , but the way you do this loop, combined with your print statements might make it look that way (54, e.g is divisible by both 2 and 3, so it will get printed twice).

(see perldoc -f last on your system's documentation to get a handle on how to use last).

HTH, and good luck.

Replies are listed 'Best First'.
Re: Re: Newbie Question on pushing Arrays
by m_heimburger (Initiate) on May 04, 2001 at 20:43 UTC
    Thanks for your help! I tried to implement most of your improvements and I think I've got them working now - but I've still got that weird problem with the array. When it divides by all the numbers in the array, it doesnt always start from 2 (the first element). If you look at the output it seems that in the end it does divide by all of them, but doesn't start with the first element. In doing so it works some bits out twice. For example if you set the limit to 13 then it will divide 11 by 2,3,5 and 7. Now it should realize that it 11 is prime and add it into the array. But when it then starts working on 12, it starts of by dividing by 11 instead of 2. I thought the push function added the value on to the end of the array? Well it doesn't really matter, but I guess it makes the program quite a bit slower, especially with larger numbers. Thanks in advance, Martin
    print "Set a limit\n"; $limit = <STDIN>; chomp $limit; @primes = (2); $zahl = 2; $isprime = 1; for (my $number = 3; $number < $limit; $number++) { @primes = sort @primes; $isprime = 1; foreach $divisor (@primes) { print "Dividing $number by $divisor\n"; if ($number % $divisor == 0) { #print "$number is no Primenumber\n"; @primes = sort @primes; $isprime = 0; last; } } if ($isprime == 1) { #print "$number is a primenumber\n"; @primes = sort @primes; push (@primes, $number); } }
      This odd behavior occurs because of how you sort the list of primes: @primes = sort @primes; The default sort uses string comparison. Just like 'aa' comes before 'b', so '11' comes before '2'. What you meant is to sort the array numerically: @primes = sort { $a <=> $b } @primes; However, since you're creating the array in order to begin with, sorting it is redundant. You should just remove the sorting line, and you script will work great.
      Your problem is that you keep sorting the list of prime numbers. First of all, this should be unnecessary, since you add them to the list in sequential order.

      But in this case, it also causes confusion, since you sorted the list in alphabetical order. Hence, 11 comes before 2. The real solution is to remove both of the sorts from your code.

      But if for some reason you actually did need to sort them, you would do this instead:

      @primes = sort { $a <=> $b } @primes

      Update: It's amazing that I generated the same content as chipmunk did, but that it took me so much longer. I really have to work on my typing skills...

      buckaduck

        Cheers Guys - I changed it and it works fine now. I guess I was trying to solve the problem by sorting... but all I did was create it... :) Thanks again, Martin