Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Nested loops

by robert44444uk (Acolyte)
on Sep 13, 2015 at 13:12 UTC ( [id://1141830]=perlquestion: print w/replies, xml ) Need Help??

robert44444uk has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks. I've managed to get the following modular exercise to work, which looks at a range of integers, and provides the total of those which are not divisible by 13 or 17.

#!/usr/bin/env perl use warnings; use strict; use feature ':5.10'; use File::Slurp; my @lines = (1..2310) ; my @s = (13,17); my @list1 = (0..$s[0]-1); my @list2 = (0..$s[1]-1); foreach $a (@list1) { my @remain1 = grep { $_% $s[0] ne $a} @lines; foreach $b (@list2) { my @remain2 = grep { $_% $s[1] ne $b} @remain1; say $s[0], " ", $a, " ",$s[1]," ", $b, " ", scalar @remain2; } }

# but the text below which plans to add a further prime number to the integer sequence and puts in a further nested foreach loop, does not work. It gives messages that $c is not defined.

#!/usr/bin/env perl use warnings; use strict; use feature ':5.10'; use File::Slurp; my @lines = (1..2310); my @s = (13,17,19); my @list1 = (0..$s[0]-1); my @list2 = (0..$s[1]-1); my @list3 = (0..$s[2]-1); foreach $a (@list1) { my @remain1 = grep { $_% $s[0] ne $a} @lines; foreach $b (@list2) { my @remain2 = grep { $_% $s[1] ne $b} @remain1; foreach $c (@list3) { my @remain3 = grep { $_% $s[2] ne $c} @remain2; say $s[0], " ", $a, " ",$s[1]," ", $b, " ", $s[2]," ", $c, + " ", scalar @remain3; } } }

#I'm not sure what I am doing wrong here. BTW I am totally new to perl and to programming - this is my very first perl program!

Replies are listed 'Best First'.
Re: Nested loops
by nuance (Hermit) on Sep 13, 2015 at 13:42 UTC
    $a and $b are special variables in perl, $c isn't.

    You have forgotten to put my statements in your foreach loops. The $a and $b that you're using are package variables that exist, so you don't get a waring. $c is not a pre-existing package variable so you get a warning.

    It's probably not a great idea to use $a and $b at all. If you were going to, the loops need to look like

    foreach my $a (@list1)

    Nuance

      Ahh, that's very kind, nuance. I keep forgetting to put "my" at the front of these things.

        As nuance stated, $a and $b are special variables to perl (used in things like sort. They don't need to be declared with my because of this). It's highly advisable that you don't use these special variables except for where they are normally expected.

        $a and  $b are just the beginning of Perl's pre-defined special variables. Please see perlvar (or perldoc perlvar on your local machine) for the whole story.


        Give a man a fish:  <%-{-{-{-<

Re: Nested loops
by Laurent_R (Canon) on Sep 13, 2015 at 15:03 UTC
    You've been given the answer to your question about $c not being defined, as well as additional material on why this does not happen with $a and $b. I will not comment further on that.

    In my humble opinion, your algorithm is quite poor. The simple fact that, when given a third number to check, you need to add another nested loops, shows that this is not quite right.

    You need an algorithm that will still work without any code change even if we add one, two or more numbers to the list of divisors to check.

    You could use two different routes.

    One is to loop on your range of integers and, for each of them, check if it is a multiple of the numbers stored in @s, and to store it in a @result array (or to print it out) it it is not a multiple of any of the @s numbers.

    The other one would be to calculate all the multiples of the numbers in @s that are smaller than your upper bound, store them in a hash, and grep on that hash the full range.

    Update: A short one-liner test showing the second option above (a variation on the sieve of Eratosthenes algorithm for prime numbers):

    $ perl -e 'my @lines = (1..2310) ; my @s = (13, 17); my %multiples; > for my $div (@s) { > $multiples{$_ * $div} = 1 for 1..200; > } > my @result = grep {not exists $multiples{$_} } @lines; > print "@result"; > ' 1 2 3 4 5 6 7 8 9 10 11 12 14 15 16 18 19 20 21 22 23 24 25 27 28 29 3 +0 31 32 33 35 36 37 38 40 41 42 43 44 45 46 47 48 49 50 53 54 55 56 5 +7 58 59 60 61 62 63 64 66 67 69 70 71 72 73 74 75 76 77 79 80 81 82 8 +3 84 86 87 88 89 90 92 93 ... 2299 2300 2302 2303 2304 2305 2306 2307 2308 2309 2310

      Thank you all for your contributions and thank you Laurent_R for your improved code

        Hi robert44444uk,

        Just to further add to what the Monks above have imparted - ever heard of recursion?

        #! perl -slw use strict; sub count_id (\@\@); # "count indivisible dividends" fnc prototype sub count_id (\@\@) { my ($divisors,$range) = (shift,shift); return 0 unless @$range && @$divisors; # check terminal condition # apply the $divisors to the dividend for this recursive call my ($aggregate,$dividend) = (0,pop @$range); for (@$divisors) { return count_id(@$divisors,@$range) if !($divid +end % $_); } return 1 + count_id(@$divisors,@$range); } my @divisors = (13,17,19); my @range = (1..2310); print "Number of indivisible items: ",count_id(@divisors,@range),"\n"; __END__
Re: Nested loops
by danaj (Friar) on Sep 16, 2015 at 02:58 UTC

    use ntheory ":all"; use feature "say"; say scalar(grep { gcd($_,13*17*19)==1 } 1..2310);

    Seems much easier than all the looping or recursion. The gcd will return 1 if the two inputs have no common factors -- if it isn't divisible by 13, 17, or 19 in this example.

      Hi danaj, fancy seeing you here! Thank you for this, will give it a work through when I get some time. You know why I am trying to do this program from Mersenneforum and it will need to be pretty efficient as I want to add more primes to get to an under-researched prime gap formula. Hard to beat your 1 liner, I think.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1141830]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (3)
As of 2024-04-25 17:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found