calculating the difference in value between data

Step three in this code calculates the difference between the one value and the next.

the results shown :
232      356      434      767      786      854      avg 571.50      group 0011100210
232      124      78      333      19      68      avg 142.33      

the second line is the difference between the numbers on the first line.

The first entry on the second line reads 232. This should read 0, as we dont need the value from the start here.
Could the code be altered to reflect this ?


#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use List::Util qw(sum);
 
##### Open files
open(my $IN,"invim2.vim") or die "Could not open input: $!\n";
open(my $OUT,">outvim2.vim") or die "Could not open output: $!\n";
 
my @avgs1;
my @avgs2;
my ($maxavg1, $minavg1, $maxavg2, $minavg2);
 
##### Step 1: read a line, and split it on comma
while(<$IN>){
        chomp;
        my @arr = split /,/;
        next unless @arr;
 
 
        # discard 1st and 2nd last and last item
        shift @arr; 
	pop @arr;
	pop @arr;
	# pop @arr;
 
 
        ##### Step 2: Sort data into ascending order
        @arr = sort {$a <=> $b} @arr;
        print "arr @arr\n";
 
 
        ##### Step 3: Calculate difference between neighboring pairs
        my @diff = ($arr[0], map {$arr[$_] - $arr[$_-1]} (1..$#arr));
        print "diff @diff\n";
 
 
        ##### Step 4: Calculate amount in each group
        my @groups = (0)x10;
        foreach my $a (@arr) {
                $groups[$a/100]++;
        }
        print "group @groups\n";
 
 
        ##### Step 5: Calculate average
 
        my $avg1 = sum(@arr)/@arr;
        printf "arr avg %.2f\n", $avg1;
        if(!$maxavg1 || $avg1 > $maxavg1) { $maxavg1 = $avg1; }
        if(!$minavg1 || $avg1 < $minavg1) { $minavg1 = $avg1; }
        push @avgs1, $avg1;
 
        my $avg2 = sum(@diff)/@diff;
        printf "diff avg %.2f\n", $avg2;%.2f
        if(!$maxavg2 || $avg2 > $maxavg2) { $maxavg2 = $avg2; }
        if(!$minavg2 || $avg2 < $minavg2) { $minavg2 = $avg2; }
        push @avgs2, $avg2;
 
        ##### Step 6: Print results
	
	
 
 
        print $OUT join("\t", @arr) . "\tavg " . sprintf("%.2f\t", $avg1) . "group " . join("", @groups) . "\n";
        print $OUT join("\t", @diff) . "\tavg " . sprintf("%.2f\t", $avg2) . "\n";
        print $OUT "\n";
}
 
 
	printf "input: maxavg %d minavg %d avgavg %d\n", $maxavg1, $minavg1, sum(@avgs1)/@avgs1;
	printf $OUT "For data values:\t\t avg avg %.2f\t maximum avg %.2f\t minimum avg %.2f \n", sum(@avgs1)/@avgs1, $maxavg1, $minavg1 ;
	printf "diff: maxavg %d minavg %d avgavg %d\n", $maxavg2, $minavg2, sum(@avgs2)/@avgs2;
	printf $OUT "For data difference values:\t avg avg %.2f\t maximum avg %.2f\t minimum avg %.2f \n", sum(@avgs2)/@avgs2, $maxavg2, $minavg2, ;
 
	
 
close($IN);
close($OUT);

Open in new window

Europa MacDonaldChief slayer of dragonsAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

ozoCommented:
       my @diff = (0, map {$arr[$_] - $arr[$_-1]} (1..$#arr));
But do you want a 0 there, or should there be no value there?
        my @diff =  map {$arr[$_] - $arr[$_-1]} (1..$#arr);
0
mrjoltcolaCommented:
Hi Michael, looks like the program got corrupted in your cut and paste. I'll modify from my local copy from last night.
0
mrjoltcolaCommented:

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use List::Util qw(sum);
 
##### Open files
open(my $IN,"invim2.vim") or die "Could not open input: $!\n";
open(my $OUT,">outvim2.vim") or die "Could not open output: $!\n";
 
my @avgs1;
my @avgs2;
my ($maxavg1, $minavg1, $maxavg2, $minavg2);
 
##### Step 1: read a line, and split it on comma
while(<$IN>){
        chomp;
        my @arr = split /,/;
        next unless @arr;
 
        # discard 1st and last item
        shift @arr; pop @arr;
 
        ##### Step 2: Sort data into ascending order
        @arr = sort {$a <=> $b} @arr;
        print "arr @arr\n";
 
        ##### Step 3: Calculate difference between neighboring pairs
        my @diff = (0, map {$arr[$_] - $arr[$_-1]} (1..$#arr));
        print "diff @diff\n";
 
        ##### Step 4: Calculate amount in each group
        my @groups = (0)x5;
        foreach my $a (@arr) {
                $groups[$a/10]++;
        }
        print "group @groups\n";
        ##### Step 6: Calculate average
 
        my $avg1 = sum(@arr)/@arr;
        printf "arr avg %.2f\n", $avg1;
        if(!$maxavg1 || $avg1 > $maxavg1) { $maxavg1 = $avg1; }
        if(!$minavg1 || $avg1 < $minavg1) { $minavg1 = $avg1; }
        push @avgs1, $avg1;
 
        my $avg2 = sum(@diff)/@diff;
        printf "diff avg %.2f\n", $avg2;
        if(!$maxavg2 || $avg2 > $maxavg2) { $maxavg2 = $avg2; }
        if(!$minavg2 || $avg2 < $minavg2) { $minavg2 = $avg2; }
        push @avgs2, $avg2;
 
        ##### Step 5: Print results
        print $OUT join("\t", @arr) . "\tavg " . sprintf("%.2f\t", $avg1) . "group " . join("", @groups) . "\n";
        print $OUT join("\t", @diff) . "\tavg " . sprintf("%.2f\t", $avg2) . "\n";
        print $OUT "\n";
}
 
printf "input: maxavg %d minavg %d avgavg %d\n", $maxavg1, $minavg1, sum(@avgs1)/@avgs1;
printf $OUT "maxavg %d minavg %d avgavg %d\n", $maxavg1, $minavg1, sum(@avgs1)/@avgs1;
printf "diff: maxavg %d minavg %d avgavg %d\n", $maxavg2, $minavg2, sum(@avgs2)/@avgs2;
printf $OUT "maxavg %d minavg %d avgavg %d\n", $maxavg2, $minavg2, sum(@avgs2)/@avgs2;
 
close($IN);
close($OUT);

Open in new window

0
Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

Europa MacDonaldChief slayer of dragonsAuthor Commented:
hi mrjoltcola,

it want corrupted, I had altered some parts today

0
Europa MacDonaldChief slayer of dragonsAuthor Commented:
at step 3,

instead of finding the first value difference (232 in the above example)

the first value difference should not be there
0
Europa MacDonaldChief slayer of dragonsAuthor Commented:
maybe it has been corrupted, cant get it to work now
0
mrjoltcolaCommented:
I got syntax errors without any mods to your code.

Number found where operator expected at t.pl line 56, near "%.2"
        (Missing operator before 2?)
Bareword found where operator expected at t.pl line 56, near "2f"
        (Missing operator before f?)
syntax error at t.pl line 56, near "%.2"
syntax error at t.pl line 69, near "}"
Execution of t.pl aborted due to compilation errors.
0
Europa MacDonaldChief slayer of dragonsAuthor Commented:
now Im lost again. What are mods ?
0
mrjoltcolaCommented:
I'm a little confused because on the previous mod I made to this it was to add the 1st value in the diff array, now you want it removed.

Here you go.

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;
use List::Util qw(sum);
 
##### Open files
open(my $IN,"invim2.vim") or die "Could not open input: $!\n";
open(my $OUT,">outvim2.vim") or die "Could not open output: $!\n";
 
my @avgs1;
my @avgs2;
my ($maxavg1, $minavg1, $maxavg2, $minavg2);
 
##### Step 1: read a line, and split it on comma
while(<$IN>){
        chomp;
        my @arr = split /,/;
        next unless @arr;
 
 
        # discard 1st and 2nd last and last item
        shift @arr;
        pop @arr;
        pop @arr;
        # pop @arr;
 
 
        ##### Step 2: Sort data into ascending order
        @arr = sort {$a <=> $b} @arr;
        print "arr @arr\n";
 
 
        ##### Step 3: Calculate difference between neighboring pairs
        my @diff = (map {$arr[$_] - $arr[$_-1]} (1..$#arr));
        print "diff @diff\n";
 
 
        ##### Step 4: Calculate amount in each group
        my @groups = (0)x10;
        foreach my $a (@arr) {
                $groups[$a/100]++;
        }
        print "group @groups\n";
 
 
        ##### Step 5: Calculate average
 
        my $avg1 = sum(@arr)/@arr;
        printf "arr avg %.2f\n", $avg1;
        if(!$maxavg1 || $avg1 > $maxavg1) { $maxavg1 = $avg1; }
        if(!$minavg1 || $avg1 < $minavg1) { $minavg1 = $avg1; }
        push @avgs1, $avg1;
 
        my $avg2 = sum(@diff)/@diff;
        printf "diff avg %.2f\n", $avg2;
        if(!$maxavg2 || $avg2 > $maxavg2) { $maxavg2 = $avg2; }
        if(!$minavg2 || $avg2 < $minavg2) { $minavg2 = $avg2; }
        push @avgs2, $avg2;
 
        ##### Step 6: Print results
 
 
 
 
        print $OUT join("\t", @arr) . "\tavg " . sprintf("%.2f\t", $avg1) . "group " . join("", @groups) . "\n";
        print $OUT join("\t", @diff) . "\tavg " . sprintf("%.2f\t", $avg2) . "\n";
        print $OUT "\n";
}
 
 
        printf "input: maxavg %d minavg %d avgavg %d\n", $maxavg1, $minavg1, sum(@avgs1)/@avgs1;
        printf $OUT "For data values:\t\t avg avg %.2f\t maximum avg %.2f\t minimum avg %.2f \n",
                        sum(@avgs1)/@avgs1, $maxavg1, $minavg1 ;
        printf "diff: maxavg %d minavg %d avgavg %d\n", $maxavg2, $minavg2, sum(@avgs2)/@avgs2;
        printf $OUT "For data difference values:\t avg avg %.2f\t maximum avg %.2f\t minimum avg %.2f \n",
                        sum(@avgs2)/@avgs2, $maxavg2, $minavg2, ;
 
 
 
close($IN);
close($OUT);

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Europa MacDonaldChief slayer of dragonsAuthor Commented:
yes, you are right. Thank you. dont be confused, we did want it added, but have realised since that it affects the average in a false way, we didnt see that yesterday

thankyou
0
Europa MacDonaldChief slayer of dragonsAuthor Commented:
thank you :)
0
mrjoltcolaCommented:
I only changed one line (besides reformatting a couple of lines that were too long into shorter lines)


Original:

my @diff = (0, map {$arr[$_] - $arr[$_-1]} (1..$#arr));

Changed:

my @diff = (map {$arr[$_] - $arr[$_-1]} (1..$#arr));


Actually also what ozo suggested above.
0
Europa MacDonaldChief slayer of dragonsAuthor Commented:
if you were to right this in English, what would you be saying ?


my @diff = (0, map {$arr[$_] - $arr[$_-1]} (1..$#arr));
0
mrjoltcolaCommented:
diff list equals new list (0) plus list (for each number "i" in arr list from 1 to end, subtract value of number in "i - 1")
0
ozoCommented:
my @diff = (map {$arr[$_] - $arr[$_-1]} (1..$#arr));
is what I said
0
Europa MacDonaldChief slayer of dragonsAuthor Commented:
sorry ozo, I didnt understand what you did. I copied it into my script and couldnt get it to work for me.
0
Europa MacDonaldChief slayer of dragonsAuthor Commented:
Im a complete beginner at this. I am scraping my way through with the help of you guys
0
mrjoltcolaCommented:
The difference in what ozo said:

(map {$arr[$_] - $arr[$_-1]} (1..$#arr));

and:

(0, map {$arr[$_] - $arr[$_-1]} (1..$#arr));


Is just the 1st element in the list. In Perl you can create list expressions out of other elements or lists by just listing comma delimited as:

(0, 1, 2, ...)
0
Europa MacDonaldChief slayer of dragonsAuthor Commented:
should  I reassign points ?
0
ozoCommented:
How did you copy it it into your script, and in what way did it not work?
0
ozoCommented:
see
 List value constructors
in
perldoc perldata
0
Europa MacDonaldChief slayer of dragonsAuthor Commented:
well I just copied it over, and as the program ran, the command prompt window just flashed past and there was no creation of the output file. At tha point I just went with mrjolt's code

I dont really know enough to say at this point. I really am learning this as I go along. Your code was fine, it is my inability that is the problem . .. .
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Perl

From novice to tech pro — start learning today.