Bug in Perl 5 Sieve?

I am able to get the first two tests of Sieve of Eratosthenes to pass, but after that things start to get…strange.

Here is my completed code:

package Sieve;

use v5.38;

use Exporter qw<import>;
our @EXPORT_OK = qw<find_primes>;

our (@primes, @marked, $limit);

sub find_primes ($limit) {
    our @array = (2..$limit);
    for my $i (@array) {
        next if grep { $_ == $i } @marked;
        push(@primes, $i);
        my $composite = $i;
        while ($composite <= $limit) {
            $composite = $composite + $i;
            push(@marked, $composite); 
    return \@primes;

Here is test 3…why is the number 2 not included in the check? Then it really gets weird.

Test 5, my output does this strange loop a couple of times before it finally gets going. I have tested this in my perl interpreter locally in Ubuntu and this issue does not occur.

Am I crazy? :dizzy_face:

You are using a variable outside of the scope of your subroutine. Every time that subroutine is run, @primes will contain the contents of previous test runs.

Re: your question “why is the number 2 not included in the check?”
The output only shows the content of the array which did not match the expected values. In the PATH column, it shows each index of the array where the check failed. It does not show [0] because a 2 is present and correct.

It may be helpful to add some data dumping to your code to get the full picture of what is being returned. If you change the last line to

return ::YYY(\@primes);

you will get the full content of @primes output in YAML format.

1 Like

I understand now. I did not realize that the subroutine was being called multiple times in the test. I fixed it by clearing the array at the start of the subroutine. Not sure if it is the most elegant solution, but it did pass the tests. Thank you for all your help and explanation.

I just ran into something very similar where a nested while loop cannot access the variables defined with my in the parent loop. If using our results in scoping problems, what is the best way to actually handle this? Just rewrite functions to avoid nested loops, or avoid globals?

Is there a sane way to pass scoped variables down to descendant loops?

EDIT: My code was just bad and I’ve been staring at it too long. The issues I was attributing to scoping don’t seem to be?
Based on stack overflow answers (though they’re super old ones) I should not use global arrays