1 #!/usr/bin/perl
  2 # https://theweeklychallenge.org/blog/perl-weekly-challenge-204/#TASK2
  3 #
  4 # Task 2: Reshape Matrix
  5 #
  6 # You are given a matrix (m x n) and two integers (r) and (c).
  7 #
  8 # Write a script to reshape the given matrix in form (r x c) with the original
  9 # value in the given matrix. If you can’t reshape print 0.
 10 #
 11 ## Example 1
 12 ##
 13 ## Input: [ 1 2 ]
 14 ##        [ 3 4 ]
 15 ##
 16 ##        $matrix = [ [ 1, 2 ], [ 3, 4 ] ]
 17 ##        $r = 1
 18 ##        $c = 4
 19 ##
 20 ## Output: [ 1 2 3 4 ]
 21 #
 22 ## Example 2
 23 ##
 24 ## Input: [ 1 2 3 ]
 25 ##        [ 4 5 6 ]
 26 ##
 27 ##        $matrix = [ [ 1, 2, 3 ] , [ 4, 5, 6 ] ]
 28 ##        $r = 3
 29 ##        $c = 2
 30 ##
 31 ## Output: [ [ 1, 2 ], [ 3, 4 ], [ 5, 6 ] ]
 32 ##
 33 ##         [ 1 2 ]
 34 ##         [ 3 4 ]
 35 ##         [ 5 6 ]
 36 #
 37 ## Example 3
 38 ##
 39 ## Input: [ 1 2 ]
 40 ##
 41 ##        $matrix = [ [ 1, 2 ] ]
 42 ##        $r = 3
 43 ##        $c = 2
 44 ##
 45 ## Output: 0
 46 #
 47 ############################################################
 48 ##
 49 ## discussion
 50 ##
 51 ############################################################
 52 #
 53 # So first we check our input to find m and n from our (m x n) matrix.
 54 # If then m*n != $r * $c we can return 0 right away.
 55 # Otherwise, flatten the matrix and select $r arrays of $c elements
 56 # as the new matrix.
 57 #
 58 use strict;
 59 use warnings;
 60 
 61 my @examples = (
 62    [ [ [ 1, 2 ], [ 3, 4 ] ], 1, 4 ],
 63    [ [ [ 1, 2, 3 ], [ 4, 5, 6] ], 3, 2],
 64    [ [ [ 1, 2 ] ], 3, 2]
 65 );
 66 foreach my $example (@examples) {
 67    my ($matrix, $r, $c) = @$example;
 68    print_reshaped_matrix($matrix, $r, $c);
 69 }
 70 
 71 # given the matrix, $r and $c let's reshape the matrix
 72 sub print_reshaped_matrix {
 73    my ($matrix, $r, $c) = @_;
 74    # print the input matrix first
 75    print "Input:\n";
 76    print_matrix($matrix);
 77    # fetch the individual arrays from the matrix and
 78    # calculate m and n
 79    my @arrays = @$matrix;
 80    my $n = scalar(@arrays);
 81    my $m = scalar(@{$arrays[0]});
 82    # sanity check to see whether this is actually a matrix
 83    foreach my $array (@arrays) {
 84       die "Not a matrix" if scalar(@$array) != $m;
 85    }
 86    # m*n != $r*$c => we can't create the output matrix, exit immediately
 87    if ($r*$c != $m*$n) {
 88       print "Output: 0\n";
 89       return;
 90    }
 91    # flatten the matrix
 92    my @elements = flatten($matrix);
 93    my @result = ();
 94    # calculate the arrays for the target matrix
 95    foreach my $index (0..$r-1) {
 96       # calculate the current slice. It starts at $index * $c,
 97       # while the end is one less than the beginning of the next
 98       # slice (or the end of data)
 99       my $start = $index * $c;
100       my $end = ($index+1) * $c - 1;
101       # get the slice and push it onto the result matrix
102       my @tmp = @elements[$start..$end];
103       push @result, [ @tmp ];
104    }
105    # print the output
106    print "Output:\n";
107    print_matrix(\@result);
108 }
109 
110 # flatten a matrix into an array
111 sub flatten {
112    my $matrix = shift;
113    my @elements = ();
114    foreach my $array (@$matrix) {
115       push @elements, @$array;
116    }
117    return @elements;
118 }
119 
120 # print a given matrix
121 sub print_matrix {
122    my $matrix = shift;
123    my $first = 1;
124    print "[ " unless scalar(@$matrix) == 1;
125    foreach my $array (@$matrix) {
126       if($first) {
127          $first = 0;
128       } else {
129          print " , ";
130       }
131       print "[ " . join(", ", @$array) . " ]";
132    }
133    print " ]" unless scalar(@$matrix) == 1;
134    print "\n";
135 }
136