Reputation: 373
I have this code
if (@row1) {
die "Bad format!" if @row1 != @row2;
my @new = map { abs ($row2[$_] - $row1[$_]) } 0..$#row2;
which is resulting the absolute value of row2 -row1.
I tried instead of the abs (row2-row1) to find the absolute value of element 2 -element 1 of the same line of each of all the line, in continuity of upper code. My goal is to obtain the abs(row2 -row1) --> from the new values --> second element -first element of the same line for all the lines.
1 2 3 4
1 4 3 4
1 5 2 3
to become
0 2 0 0
0 1 1 1
which is already done and then to have the final output
2 2 0
1 0 1
So I edited the upper code to:
for ($i=1,$i++,$i>$row){
my @new1 = map { abs ($row1[$2+$i] - $row1[$1+$i]) } 0..$#row1;
say join " ", @new1;}
but I got "Use of uninitialized value $i in addition". I also substitute $i with "my$i" as well as with "i" and go the same errors. Could someone can explain to me why what I'm trying is wrong?
Upvotes: 1
Views: 196
Reputation: 6798
OP's question is not very clear what he wants to do with the data.
My understanding is that he would like to apply vertical and horizontal abs diff recursively.
To simplify processing code, two subroutines was implemented abs_vdiff and abs_hdiff.
#!/usr/bin/perl
#
# USAGE:
# prog.pl
#
# Description:
# Demonstration code for StackOverflow Q59945359
#
# StackOverflow:
# Question 59945359
#
# Author:
# Polar Bear
#
# Date: Tue Jan 28 13:35:00 PST 2020
#
use strict;
use warnings;
use feature 'say';
my $array = read_array();
my $vdiff = abs_vdiff($array);
my $hdiff = abs_hdiff($vdiff);
say "Read array";
show($array);
say "ABS vertical diff";
show($vdiff);
say "ABS horizontal diff";
show($hdiff);
say "We done";
sub read_array {
my @data;
while( <DATA> ) {
my @row = split ' ';
push @data, \@row;
}
return \@data;
}
sub abs_vdiff {
my $array = shift;
my @result;
foreach my $i ( 1..$#{$array} ) {
my @data = map { abs(@{@{$array}[$i]}[$_]-@{@{$array}[$i-1]}[$_]) } 0..$#{@{$array}[$i]};
push @result, \@data;
}
return \@result;
}
sub abs_hdiff {
my $array = shift;
my @data;
foreach my $row (@{$array}) {
my @row = map { abs(@{$row}[$_]-@{$row}[$_+1]) } 0..$#{$row}-1;
push @data, \@row;
}
return \@data;
}
sub show {
my $array = shift;
foreach my $row ( @{$array} ) {
say join ' ', @{$row};
}
}
__DATA__
1 2 3 4
1 4 3 4
1 5 2 3
Output
Read array
1 2 3 4
1 4 3 4
1 5 2 3
ABS vertical diff
0 2 0 0
0 1 1 1
ABS horizontal diff
2 2 0
1 0 0
We done
Upvotes: 0
Reputation: 6798
One of many possible solutions to the problem
use strict;
use warnings;
use feature 'say';
use Data::Dumper;
my $debug = 0; # debug flag
my $flag = 1;
my @current;
my @previous;
my @final;
say "First stage";
while( <DATA> ) {
@current = split ' ';
if( $flag ) {
@previous = @current;
$flag = 0;
next;
}
if( $#current != $#previous ) {
say "Ops, lines have different number of elements";
say "Previous: " . join ' ', @previous;
say "Current: " . join ' ', @current;
} else {
my @data = map { abs($current[$_]-$previous[$_]) } 0..$#current;
say join ' ', @data;
push @final, \@data;
}
@previous = @current;
}
print Dumper(\@final) if $debug;
say "Second stage";
foreach my $row (@final) {
my @data = map { abs(@{$row}[$_]-@{$row}[$_+1]) } 0..$#{$row}-1;
say join ' ', @data;
}
__DATA__
1 2 3 4
1 4 3 4
1 5 2 3
Output
First stage
0 2 0 0
0 1 1 1
Second stage
2 2 0
1 0 0
Upvotes: 0
Reputation: 386331
my @rows = (
[ 1, 2, 3, 4 ],
[ 1, 4, 3, 4 ],
[ 1, 5, 2, 3 ],
);
my $num_cols = @{ $rows[0] };
for my $r (1..$#rows) {
die "Bad format!" if @{ $rows[$r] } != $num_cols;
my @diffs = map { abs($rows[$r-1][$_] - $rows[$r][$_]) } 0..$num_cols-1;
my @diff_diffs = map { abs($diffs[$_-1] - $diffs[$_]) } 1..$num_cols-1;
say "@diff_diffs";
}
Upvotes: 2