• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 163
  • Last Modified:

Creating diagonal array but retaining first n columns.

This is sort of a continuation of  question I previously asked, which was:

http://www.experts-exchange.com/Programming/Programming_Languages/Perl/Q_21857321.html

Please see the comments after the accepted answer posting.

An Expert provided this code:

for( \@ary1, \@ary2, \@ary3 ){
    my $right=@{$_->[0]};
    my $left=@combinedary&&@{$combinedary[0]};
    push @$_,(0)x$right for @combinedary;
    push @combinedary,[(0)x$left, @$_] for @$_;
}

The idea is to combined multiple arrays and create a "diagonal" of values and fill with zeros everywhere else, which is exactly what the above code accomplishes.  But for this question, I would like to retain the first n columns.  Please see below for a detailed description.  This example only combines two arrays but the solution should apply to two or more arrays.

@ary1 = (
[1,2,3,4]
);

@ary2 = (
[10,9,8]
);

If n==2, then the final array would be:
@final = (
[1,2,3,4,0],
[10,9,0,0,8]
),

if n==1, then the final array would be:
@final = (
[1,2,3,4,0,0],
[10,0,0,0,9,8]
);

Another way to think of this would be to add @ary1 and @ary2:

@combined = (
[1,2,3,4],
[10,9,8]
);

Then split after n columns:
n==2:
@left = (
[1,2],
[10,9]
);

@right = (
[3,4],
[8]
);

Apply the above zero padding method to @right but leave @left alone:
@right_result = (
[3,4,0],
[0,0,8]
);

Finally, put @left and @right_result together:
@rightleft = (
[1,2,3,4,0]
[10,9,0,0,8]
);
0
mock5c
Asked:
mock5c
  • 3
1 Solution
 
Adam314Commented:
For the zero padding, You want the first array to have all padding to the right, the each array after that to have padding to the left such that it's 3rd (if n=2) element is 1 column after the last elemnt of the previous array?

0
 
Adam314Commented:
Building on the code from before:




#!/usr/bin/perl
use strict;
use Data::Dumper;

my @ary1 = (
[1,2,3,4]
);

my @ary2 = (
[10,9,8]
);

#Combine arrays.  First argument is number of elements to keep, remaining arguments are pointers to arrays
my @arrfinal=Combine(2,\@ary1, \@ary2);
print Dumper(\@arrfinal);

#This subroutine will combine all arrays passed to it
sub Combine {
      my ($NumToKeep,@ArrPtr)=@_;
      my (@left,@combinedary);
      
      #Create left, the remaining is right
      foreach my $arr (@ArrPtr){
            #push @left, [];
            foreach my $row (@{$arr}){
                  push @left, [];
                  #push @{$left[-1]}, [];
                  #push @{${$left[-1]}[-1]}, shift @{$row} for (1..$NumToKeep);
                  push @{$left[-1]}, shift @{$row} for (1..$NumToKeep);
            }
      }
      
      #This is the same code from before
      for( @ArrPtr ){
          my $right=@{$_->[0]};
          my $left=@combinedary&&@{$combinedary[0]};
          push @$_,(0)x$right for @combinedary;
          push @combinedary,[(0)x$left, @$_] for @$_;
      }
      
      #Combine the two arrays
      foreach my $row (@left){
            my $combrow=shift @combinedary;
            push @$row, shift @{$combrow} while $#{$combrow}>=0;
      }
      return @left;
}

0
 
Adam314Commented:
Some lines are commented out... you can delete those - they were there for debugging
0
 
ozoCommented:
$n=2;
@combinedary=();
for( \@ary1, \@ary2, \@ary3 ){
    my @right=(0)x(@{$_->[0]}-$n);
    my @middle=(0)x((@combinedary&&@{$combinedary[0]})-$n);
    push @$_,@right for @combinedary;
    push @combinedary,[@$_[0..$n-1],@middle, @$_[$n..$#$_]] for @$_;
}
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now