more useful options PerlMonks

Re: Perl vs. Python for prime numbers

by LanX (Chancellor)
 on Jun 13, 2013 at 23:14 UTC ( #1038858=note: print w/replies, xml ) Need Help??

in reply to Perl vs. Python for prime numbers

OK no comment about the algorithm, I take this as a constructed case for comparison of two languages.

The first approach is a variation of chorobas code, but a bit more intuitive from my perspective.

The second is a generic approach using goto. This technique can always emulate this (very) Python idiom.

```#!/usr/bin/perl
use warnings;
use strict;
use feature qw(say);

N:
for my \$n (2 .. 99) {
for my \$x (2 .. \$n - 1) {
next N if 0 == \$n % \$x;
}
say \$n, ' is a prime number';
}

for my \$n (2 .. 99) {
for my \$x (2 .. \$n - 1) {
goto NOT_PRIME if 0 == \$n % \$x;
}
say \$n, ' is a prime number';
NOT_PRIME:
}

I think both are pretty good readable.

HTH! =)

Cheers Rolf

( addicted to the Perl Programming Language)

Replies are listed 'Best First'.
Re^2: Perl vs. Python for prime numbers
by hdb (Prior) on Jun 14, 2013 at 07:24 UTC

I observe that your inner loop only runs to \$n - 1 while in the Python script it runs to n. The former makes sense to me but the latter not. I know little about Python, but running the inner loop to n should produce no primes found at all. Why does it work anyway (I checked it does)? I guess this is off topic as it is a Python question...

I observerd that too, so I ran python and tried
```print(range(1,10))

Lo and behold:

```[1, 2, 3, 4, 5, 6, 7, 8, 9]
لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Actually I copied choroba's code w/o caring about the difference, but yes, as he already showed, the range built-in in Python excludes the upper bound.

Makes sense from a mathematical point of view (combining different ranges is easier) but I prefer the more intuitive Perl way to do it.

Cheers Rolf

( addicted to the Perl Programming Language)

...the range built-in in Python excludes the upper bound. Makes sense from a mathematical point of view (combining different ranges is easier) but I prefer the more intuitive Perl way to do it.

Theoretically, I prefer semi-open ranges [begin, end), aka half-open intervals, because:

• The range size is simply "end - begin"
• Empty ranges are expressed as "begin equals end" and so do not require special handling
• Two subsequences are adjacent means that the upper bound of the one equals the lower bound of the other
This theoretical superiority was eloquently expressed in hand-written notes by Edsger W Dijkstra in 1982, who further argued that zero (not one) is the natural first array subscript, as in [0, N). With typical attention to detail, I see that the three page numbers of Dijkstra's note are: 0, 1, and 2! :)

In practice, I prefer Python semi-open ranges to the inclusive (closed) ranges emitted by the Perl and Ruby range operator. I remember finding Python's semi-open ranges nicer when golfing with string slices. After enjoying Python string slices, I miss them when coding in Perl; the closest Perl equivalent, the substr function, seems unwieldy by comparison.

Semi-open ranges also feel comfortable to me because they form a crucial part of C++ STL, in particular iterators, which in turn were influenced by C pointers and arrays. Stepanov extended some common (semi-open) C idioms, such as:

```for (i = 0; i < N; ++i) { // a[i] ... }
for (ptr = a; ptr < a+N; ++ptr)
inventing a more general iterator abstraction:
```for (iter = begin; iter != end; ++iter)
thus enabling STL algorithms to work on any container that implements the iterator interface.

References

Re^2: Perl vs. Python (for/else idiom analyzed)
by LanX (Chancellor) on Jun 15, 2013 at 11:39 UTC
As a side note: Python has no labels, and loop control statements like break are restricted to the inner loop.

So this "natural" solution in Perl (that is w/o flag variable) isn't possible in Python

```N:
for my \$n (2 .. 99) {
for my \$x (2 .. \$n - 1) {
next N if 0 == \$n % \$x;
}
say \$n, ' is a prime number';
}

Looking at a one to one translation of the flow, it bugs me that the "NOT_PRIME" part is executed after the "PRIME" part, which is quite strange in my eyes

```for my \$n (2 .. 99) {
for my \$x (2 .. \$n - 1) {
goto NOT_PRIME if 0 == \$n % \$x;
}
PRIME:
say \$n, ' is a prime number';
NOT_PRIME:
}

So to separate code which doesn't belong to the py-else branch one needs to put it into the loop into the py-if branch

so the logic of this Perl code with flag-var prime

```for my \$n (2 .. 99) {
my \$prime = 1;

for (2 .. \$n-1) {
\$prime = 0, last unless \$n % \$_;
}

if (\$prime) {
print \$n, " is ";
} else {
print \$n, " is not ";
}

print  "a prime number\n";
}

translates to

```for my \$n (2 .. 99) {
for my \$x (2 .. \$n - 1) {
if (0 == \$n % \$x) {          # py-if branch
print \$n, " is not ";
goto BREAK;                # py-break
}
}
print \$n, " is ";              # py-else branch
BREAK:
print  "a prime number\n";
}

I think now the motivation to call this statement "else" it's better understandable. But the py-docs do not seem to provide any such motivation.

Maybe it's a matter of practice, but I rather prefer the ability to have Perl labels and loop controls like next or last to address them.

And Perl's goto still gives me the freedom to emulate any python code in a 1-to-1 translation. And the naming of the label in Perl gives me additional freedom to clarify the code! ¹

Python OTOH can't emulate labels or Perl's control flow and needs to redesign the code when migrated.

See also this SO- discussion http://stackoverflow.com/questions/438844/is-there-a-label-goto-in-python for how quirky and complicated py-workarounds can become...

Cheers Rolf

( addicted to the Perl Programming Language)

¹) Please note that I named the "BREAK:"-label as "NOT_PRIME:" in my first post, thats very self-commenting and easier to understand than simply "else:"

Create A New User
Node Status?
node history
Node Type: note [id://1038858]
help
Chatterbox?
 [hippo]: yum update perl [hippo]: Other package managers are available LanX wouldn't update system Perl! [Discipulus]: prathap keerthipati might be it is better to install an alternative Perl instead and do not touch the system one [LanX]: see perlbrew for alternative Perl installations [marto]: unless you know exactly what you're doing an often saner option is to simply build another Perl rather than replace the system one

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (16)
As of 2017-03-23 10:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
Should Pluto Get Its Planethood Back?

Results (285 votes). Check out past polls.