Your code won't work for several reasons: $file is a scalar and in the context of your foreach-loop it is a list of one element. $number will be a lexical alias for $file while the single iteration of the loop happens. $number_counter will be increased once and $difference will be assigned 1, for a-(a-1)==a-a+1==1 .
Try this:
my @number = qw(3.34 3.67 4.75 4.98);
my $maxdiff = 0;
my @index = ();
foreach my $i ( 1 .. @number-1 ){
my $diff = abs( $number[$i] - $number[$i-1] );
if( $diff > $maxdiff ){
$maxdiff = $diff;
@index = ($i-1,$i);
}
}
if( @index ){
printf "%f: %f , %f\n",
$maxdiff, @number[ @index ]
}
update: of course, see perlsyn and perldata
--
http://fruiture.de | [reply] [d/l] |
| [reply] [d/l] |
Well, where do we start?
First up, foreach my $number ($file) is trying to iterate over a single value, ie the string '3.34, 3.67, 4.75, 4.98'. The code inside the loop is only going to see '3.34, 3.67, 4.75, 4.98' and not the individual values. Did you test this code? Did you put a print inside the loop to see what $number contained?
So, what you're really looking for is to split up the string in $file into the individual values. Let's have a look in perlfunc to see if there's anything available to help us...look at that...a function called split. So far, so good. Let's see how that works...
split /PATTERN/,EXPR,LIMIT
split /PATTERN/,EXPR
split /PATTERN/
split
Splits a string into a list of strings and returns that list
That sounds like the business. So, if we apply split to $file we can get get the numbers out of it - cool! But, wait, what PATTERN to use? From looking at the contents of $file we can see that each number is seperated by ", ", sheesh, that was pretty easy. So we get the line:
my @numbers = split /, /,$file;
And how do we check that @numbers contains what we think it should? We could use a print statement, something like:
print join("\n",@numbers) . "\n";
or we could run our little script in the perl debugger perl -d difference.pl, assuming of course that you've created a file called 'difference.pl' and that you have perl installed on your computer.
So what do we need to do next? We have to iterate over them calculating the differences. OK, how do we do that? The most obvious choice would be a foreach loop. And how should the iteration be defined? My personal choice would be to start from the second position and work towards the end, but you may have a different preference, it's entirely up to you - after all it's your homework and your grade. Using my choice of iteration definition gives us:
foreach my $index (1 .. $#numbers)
"Why 1?" I hear you say, "I though you said we were going to start at the second position?". We're starting at 1 because, in Perl, unless you specifically tell it otherwise, arrays are assumed to start at index 0, making index 1 the second index.
Now we're getting somewhere. Next we have to compute the difference. That's pretty easy:
my $difference = abs($numbers[$index] - $numbers[$index - 1]);
Now all we have to do is to keep track of the maximum difference. My personal preference is to use the terniary operator "?:", but, again, your homework, your grade, so feel free to use your imagination and use any construct you feel comfortable with. Of course, we must remember to initialise the variable holding the maximum difference correctly, otherwise this work will all be for nothing.
$max_difference = ($index == 1 or $difference > $max_difference)?$diff
+erence:$max_difference;
Finally, all we need to do now is to print the result:
print "$max_difference\n";
Putting the whole thing together (adding variable definitions and other appropriate code furniture):
use strict;
use warnings;
my $file='3.34, 3.67, 4.75, 4.98';
my @numbers=split /, /,$file;
my $max_difference;
foreach my $index(1 .. $#numbers) {
my $difference = abs($numbers[$index] - $numbers[$index - 1]);
$max_difference = ($index == 1 or $difference > $max_difference)?$d
+ifference:$max_difference;
}
print "$max_difference\n";
Be sure to post back and let everyone know how your grade!rdfield | [reply] [d/l] [select] |
Hi,
sounds to me like homework. But ok.
I would write it so :
#!/usr/local/perl -w
use strict;
use warnings;
my @file = ('0.13','0.14','0.14');
my $diff = 0;
my @diffVal;
for (my $i=1 ; $i< scalar(@file) ; $i++){
if ($diff < abs($file[$i-1]-$file[$i])){
$diff = abs($file[$i-1]-$file[$i]);
$diffVal[0] = $file[$i-1];
$diffVal[1] = $file[$i];
}
}
print "Difference between $diffVal[0] and $diffVal[1] is $diff\n" if (
+defined($diffVal[1]));
(It is not optimized!)
| [reply] [d/l] |
What's the point of using -w and use warnings?
And why quote numbers?
Also, your code seems to fail if all numbers are equal - it
won't generate output.
Abigail
| [reply] [d/l] [select] |
ok, -w and use warnings don't make sense.
Yes, you are correct with the equal - output and the numbers.
change
my @file = ('0.13','0.14','0.14');
my $diff = 0;
to
my @file = (0.14,0.14);
my $diff = -1;
and here you got your output
Difference between 0.14 and 0.14 is 0
| [reply] [d/l] [select] |
my @numbers = ('0.13', '0.14', '0.14', '0.19', '0.21', '0.23', '0.45')
+;
my %differences = ();
for (my $i = 0; $i < scalar(@numbers); $i++) {
next if $i == 0;
push @{$differences{($numbers[$i] - $numbers[$i - 1])}}, $numb
+ers[$i] . " - " . $numbers[$i - 1];
}
foreach (sort keys %differences) {
print STDOUT "Difference ($_) occured: ", join (', ', @{$diffe
+rences{$_}}), "\n"
}
exit 0;
I guess that's going beyond the exercise a little bit, but kind of fun and turned out this:
Difference (0) occured: 0.14 - 0.14
Difference (0.01) occured: 0.14 - 0.13
Difference (0.02) occured: 0.21 - 0.19, 0.23 - 0.21
Difference (0.05) occured: 0.19 - 0.14
Difference (0.22) occured: 0.45 - 0.23
| [reply] [d/l] [select] |
Eh, there's hardly anything correct in your program.
Is this a homework problem? Anyway, I'd do something like:
my @nums = qw /3.34 3.67 4.75 4.98/;
my $diff = -1;
for (my $i = 1; $i < @nums; $i ++) {
my $d = abs ($nums [$i] - $nums [$i - 1]);
$diff = $d if $diff < $d;
}
print "Greatest difference is $diff\n" unless $diff < 0;
Note that the above code is untested.
Abigail | [reply] [d/l] |
Just for the sake of doing it differently, and because I so love List::Util. (Thanks to merlyn for mentioning it way back here on PM.) :)
use List::Util qw(reduce);
my @num = qw/3.34 3.67 4.75 4.98/;
my @diff = map abs($num[$_-1] - $num[$_]), 1 .. $#num;
my $maxidx = reduce { $diff[$a] > $diff[$b] ? $a : $b } 0 .. $#diff;
print "|$num[$maxidx] - $num[$maxidx+1]| = $diff[$maxidx]\n" if @num >
+ 1;
Makeshifts last the longest. | [reply] [d/l] |