Array generation

P

poopdeville

Hi everybody. I'm a bit new to Perl, and I'm having some trouble
getting it to do exactly what I'd like it to. Given an array of
numerals @data, I'm trying to generate a new array whose elements are
the fractions of minima over maxima of adjacent pairs in @data. Here's
my attempt (I've defined min and max elsewhere -- they compute the
minimum and maximum of arrays of arbitrary length, for generality)

@data = (1,2,4,8,16)
sub RR {
my $upper = $#_;
@LOF = min(($_[0], $_[1])) / max(($_[0], $_[1]));
for $i (1 .. $upper - 1) {
push @LOF, min($_[$i], $_[$i+1]) / max($_[$i], $_[$i+1]);
}
print @LOF, "\n";
}

RR(@data);

This is giving me the right *form* of answer, but instead of giving me
the .5.5.5.5 I expect, it's returning 0.510.50.25. Obviously, I've
misunderstood some convention. :) Anybody see what's wrong?
Thanks,
'cid 'ooh
 
P

poopdeville

Fixing indentation, since this code is ugly without it:
Hi everybody. I'm a bit new to Perl, and I'm having some trouble
getting it to do exactly what I'd like it to. Given an array of
numerals @data, I'm trying to generate a new array whose elements are
the fractions of minima over maxima of adjacent pairs in @data. Here's
my attempt (I've defined min and max elsewhere -- they compute the
minimum and maximum of arrays of arbitrary length, for generality)

sub RR {
my $upper = $#_;
@LOF = min(($_[0], $_[1])) / max(($_[0], $_[1]));
for $i (1 .. $upper - 1) {
push @LOF, min($_[$i], $_[$i+1]) / max($_[$i], $_[$i+1]);

}
print @LOF, "\n";
}
 
J

jl_post

Here's my attempt (I've defined min and max
elsewhere -- they compute the minimum and
maximum of arrays of arbitrary length, for generality)

@data = (1,2,4,8,16)
sub RR {
my $upper = $#_;
@LOF = min(($_[0], $_[1])) / max(($_[0], $_[1]));
for $i (1 .. $upper - 1) {
push @LOF, min($_[$i], $_[$i+1]) / max($_[$i], $_[$i+1]);
}
print @LOF, "\n";
}

RR(@data);

This is giving me the right *form* of answer,
but instead of giving me the .5.5.5.5 I expect,
it's returning 0.510.50.25. Obviously, I've
misunderstood some convention. :) Anybody
see what's wrong?


I ran your program and it seems to run fine for me
(with the exception of the missing semicolon where you
first define your @data array).

Of course, I had to define my own min() and max()
functions, which is why I suspect that they are the
reasons your program is not running correctly. Try
running this code, which is essentially your exact
code but with min() and max() defined (and with
"use strict;" and "use warnings;"):

| #!/usr/bin/perl
| use strict;
| use warnings;
|
| sub min { $_[0] < $_[1] ? $_[0] : $_[1] }
| sub max { $_[0] > $_[1] ? $_[0] : $_[1] }
|
| sub RR {
| my $upper = $#_;
| my @LOF = min(($_[0], $_[1]))
| / max(($_[0], $_[1]));
| for my $i (1 .. $upper - 1) {
| push @LOF, min($_[$i], $_[$i+1])
| / max($_[$i], $_[$i+1]);
| }
| print "@LOF\n";
| }
|
| my @data = (1,2,4,8,16);
| RR(@data);
| __END__


Note that your RR() function is not the most ideal
way to write it. For one thing, you don't have to
set @LOF to a value and then loop from 1 to $upper - 1.
You could just declare @LOF, then loop from 0 to $upper - 1.
(I would also give @LOF and RR() more descriptive names
that would be more helpful to code maintainers that come
after you. (Believe me, they won't like it very
much not knowing what LOF and RR are supposed to stand
for.))

So I recommend you examine and test your min() and
max() functions. I have a feeling that's where your
error lies.

Hope this helps,

-- Jean-Luc
 
P

poopdeville

Note that your RR() function is not the most ideal
way to write it. For one thing, you don't have to
set @LOF to a value and then loop from 1 to $upper - 1.
You could just declare @LOF, then loop from 0 to $upper - 1.
(I would also give @LOF and RR() more descriptive names
that would be more helpful to code maintainers that come
after you. (Believe me, they won't like it very
much not knowing what LOF and RR are supposed to stand
for.))

So I recommend you examine and test your min() and
max() functions. I have a feeling that's where your
error lies.

Yes! Actually, the functions min and max were operating correctly
(well, I'm pretty sure. I wasn't getting compile errors at all, and
the algorithm is *very* simple) but interacted badly with RR because
used $i as an index but failed to protect it:

sub max {
my $upper = @_; # instead of " my
$upper = $#_; "
my $max = $_[0]; # and
for ($i = 0, $i < $upper, $i++) { # " for my $i (0 ..
$upper) "
if ($max < $_[$i]) {
$max = $_[$i];
}
} return $max;
}

Thinking about what the two subroutines were doing together is making
my head hurt. :) Thanks for your help and suggestions.

'cid 'ooh
 
J

jl_post

(e-mail address removed) replied:
Yes! Actually, the functions min and max were
operating correctly (well, I'm pretty sure.
I wasn't getting compile errors at all, and
the algorithm is *very* simple) but interacted
badly with RR because used $i as an index but
failed to protect it:

Ah. Well, that would have been a compile error
if you used "use strict;". That is why so many people
in this newsgroup recommend it so highly. That one
line helps catch so many errors.

I think many people don't like to use it simply
because it complains about things that aren't
necessarily errors. But more experienced Perl
programmers know that the small hassle "use strict;"
creates is miniscule compared to the hours and hours
of debugging time (literally!) you'd spend trying to
find a teeny-tiny error (like misspelling a variable
name or the error you just encountered).

Also, another piece of advice when posting to
this newsgroup via Google Groups:

Since the new "improved" Google Groups removes any
indentation at the beginning of a line (because, according
to Google, they're "wasteful and unnecessary"), you may
want to prefix every line of your code with "| ".

Therefore, a posted loop would look like this:

| foreach (1 .. 100)
| {
| print "$_\n";
| }

You can add "| " to every line of an entire file with this
one-line Perl script:

perl -pe "print '| '" program.pl

Then anyone else can strip them out of your code by typing:

perl -pi.posted -e "s/..//" program.pl

So, remember, always use "use strict;" and "use warnings;"! You'll
be glad you did when it finds more obscure errors for
you.

-- Jean-Luc
 
P

poopdeville

Also, another piece of advice when posting to
this newsgroup via Google Groups:

Since the new "improved" Google Groups removes any
indentation at the beginning of a line (because, according
to Google, they're "wasteful and unnecessary"), you may
want to prefix every line of your code with "| ".

Yes, I noticed that. Sorry for the unreadable code. I'll keep that in
mind.

So, remember, always use "use strict;" and "use warnings;"! You'll
be glad you did when it finds more obscure errors for
you.

My knowledge of Perl isn't very sophisticated, so I have no idea how to
implement this use strict stuff. But after this debugging session
(yes, I spent hours and hours on it), I'm going to learn. :)
Thanks again for your help.
'cid 'ooh
 
A

A. Sinan Unur

My knowledge of Perl isn't very sophisticated, so I have no idea how to
implement this use strict stuff.

Hmmmmm ...

#! /usr/bin/perl

use strict;
use warnings;

# Possibly also
# use diagnostics;

# Your script

__END__

All of this stuff is in the posting guidelines. It looks like you have not
read the guidelines. Go read them before you do anything else. Please.

Sinan
 
P

poopdeville

A. Sinan Unur said:
#! /usr/bin/perl

use strict;
use warnings;

Yes, I got that far. However, I have no idea what that does. No need
to explain, I'll RTFM. :)
All of this stuff is in the posting guidelines. It looks like you have not
read the guidelines. Go read them before you do anything else. Please.

I just read the 1.5 version of that document, apparently posted earlier
today. Sorry for the (slightly) incomplete script. Was that your only
complaint? (I'm trying to play nice, so if you have any more
criticism, please share. I'll listen.)

'cid 'ooh
 
A

A. Sinan Unur

Yes, I got that far. However, I have no idea what that does. No need
to explain, I'll RTFM. :)

perldoc strict
perldoc warnings

They are short and sweet.
I just read the 1.5 version of that document, apparently posted earlier
today. Sorry for the (slightly) incomplete script. Was that your only
complaint?

It is not a small issue. You need to post something other people's minds
can easily parse and, if necessary, they can run with minimal effort. The
rationale for this is explained in the document about asking smart
questions (the link to which is in the posting guidelines).

If you post something that is hard to parse (no indenting, s/// on one
line, s!!! on the next for no reason other than to mislead the reader to
thinking that there might be a reason etc), you are imposing a cost on all
the readers of this group.

Thanks.

Sinan
 
M

Michele Dondi

@data = (1,2,4,8,16)
sub RR {
my $upper = $#_;
@LOF = min(($_[0], $_[1])) / max(($_[0], $_[1]));
for $i (1 .. $upper - 1) {
push @LOF, min($_[$i], $_[$i+1]) / max($_[$i], $_[$i+1]);
}
print @LOF, "\n";
}

RR(@data);

This is giving me the right *form* of answer, but instead of giving me
the .5.5.5.5 I expect, it's returning 0.510.50.25. Obviously, I've
misunderstood some convention. :) Anybody see what's wrong?

I noticed that you've already found what was wrong and that you've
been given good advice.

As a side note I'd like to add that even if generally speaking
factorizing the code through subs is convenient, in this case min()
and max() are likely to do much of the same job (also, function calls
_with_ arguments are somewhat expensive in perl), well unless they
cache their result, which probably would introduce more work than it
would save, taking into account their simplicity.

So, personally I'd do

sub rr {
my ($old, @out)=1;
for (@_) {
my ($n,$m) = $_<$old ? ($_, $old) : ($old, $_);
push @out, $n/$m;
$old=$_;
}
shift @out;
@out;
}

or

sub rr {
my @a=@_;
shift @a;
my @out;
for (@a) {
my ($n,$m)=($_,shift);
($n,$m)=($m,$n) if $n>$m;
push @out, $n/$m;
}
@out;
}

or

sub rr {
map {
my $r=$_[$_]/$_[$_-1];
$r<1 ? $r : 1/$r;
} 1..$#_;
}

or...


Please note, as another side note that while indeed there's nothing
wrong a priori with a sub print()ing something, I used a return() list
instead, which seems more appropriate, IMHO.


Michele
 
M

Michele Dondi

perl -pe "print '| '" program.pl

perl -pe "s/^/| /" program.pl


PS: OK, I realize that yours would most probably be more efficient,
and no, I'm not testing them, for it's not relevant in this case
anyway...


Michele
 
M

Michele Dondi

My knowledge of Perl isn't very sophisticated, so I have no idea how to
implement this use strict stuff. But after this debugging session

My knowledge of Perl isn't very sophisticated either, _but_ I have no
idea what "how to implement this use strict stuff" could mean. Just at
the same time I assure you that no sophisticated knowledge of Perl is
required to C<use strict;> (or to C<use warnings;>). Just read

perldoc strict


HTH,
Michele
 
B

Brian McCauley

My knowledge of Perl isn't very sophisticated, so I have no idea how to
implement this use strict stuff.

You've got it backwards. What "use strict" does is disable three
features of Perl that you should not consider using until your knowledge
of perl _is_ sufficiently sophisticated to understand how and when it is
advisable to use these features.

See my diverting rant and argument with one of the leading lights of the
Perl community at:

http://groups-beta.google.com/group/comp.lang.perl.misc/msg/89f307d6b9e83c65
 
J

Jim Keenan

Brian said:
You've got it backwards. What "use strict" does is disable three
features of Perl that you should not consider using until your knowledge
of perl _is_ sufficiently sophisticated to understand how and when it is
advisable to use these features.
Brian:

I think we need to distinguish between two situations:

1. The point in an introductory-level Perl course at which an
instructor should introduce the use of strictures to the students -- or
the point at which someone teaching herself Perl should start using
strictures consistently.

and

2. What the readers of this Usenet news group expect posters to do to
solve their Perl problems before posting to the list.

People answer Question 1 in various ways which were extensively
discussed in the Feb 2004 thread from which your link comes
(http://groups-beta.google.com/group/comp.lang.perl.misc/msg/be8903f6ca54024c).
(Reviewing that thread, I was surprised to see that even I had staked
out a position, viz., I use Randal's book and introduce warnings and
strictures when he does.) We're never going to come to consensus as to
the one correct answer to this question. TIMTOWTDI.

But as to Question 2: While a lot of beginners post on
comp.lang.perl.misc, it is *not* a beginners' list -- at least not
"beginners" in the sense of people who have not taken the most
elementary steps needed to solve their Perl problems. Here, we expect
people to have done their homework before posting. When I read/respond
to questions on, say, perl-beginners@yahoogroups (a mailing list I
myself used as a beginner), I do not expect everyone to have turned on
'use strict;' before posting. When I read c.l.p.misc, I do.

Jim Keenan
 
P

poopdeville

Michele said:
@data = (1,2,4,8,16)
sub RR {
my $upper = $#_;
@LOF = min(($_[0], $_[1])) / max(($_[0], $_[1]));
for $i (1 .. $upper - 1) {
push @LOF, min($_[$i], $_[$i+1]) / max($_[$i], $_[$i+1]);
}
print @LOF, "\n";
}

RR(@data);

This is giving me the right *form* of answer, but instead of giving me
the .5.5.5.5 I expect, it's returning 0.510.50.25. Obviously, I've
misunderstood some convention. :) Anybody see what's wrong?

I noticed that you've already found what was wrong and that you've
been given good advice.

As a side note I'd like to add that even if generally speaking
factorizing the code through subs is convenient, in this case min()
and max() are likely to do much of the same job (also, function calls
_with_ arguments are somewhat expensive in perl), well unless they
cache their result, which probably would introduce more work than it
would save, taking into account their simplicity.

Thanks for your suggestions. As I mentioned before, my Perl knowledge
is not very sophisticated. I don't have much experience with high
level programming languages, as all my previous programming has been
done in assembly, with Turing machines, the Lambda calculus, recursive
functions, and so on (that is, outside of a bit of assembly, I've never
written machine readable code). Therefore, I'm not familiar with the
nicities that make Perl a high level language (this relates to my
remark concerning my lack of understanding of strictures. I chose Perl
for my current project because it let me get down to writing algorithms
without having to worry about a zillion details, like C for instance.
But I enjoyed writing it, and I've met nice people here, so I'll stick
with it. :)
Please note, as another side note that while indeed there's nothing
wrong a priori with a sub print()ing something, I used a return() list
instead, which seems more appropriate, IMHO.

Yes, I was using that print call while debugging. I've sinced changed
it to a return.

Thanks,
'cid 'ooh
 
M

Michele Dondi

written machine readable code). Therefore, I'm not familiar with the
nicities that make Perl a high level language (this relates to my
remark concerning my lack of understanding of strictures. I chose Perl

IMHO it relates poorly to your remark in that _not_ using strictures
in some sense increases the kind of niceties that make Perl a high
level language.

When you C<use strict;> you "pay" to have part of your freedom
reSTRICTed, when this would allow you too easily to introduce bugs in
your code.


Michele
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,166
Messages
2,570,901
Members
47,442
Latest member
KevinLocki

Latest Threads

Top