Peter
Peter Campbell Smith

Climbing or falling
and reshaping the matrix

Weekly challenge 204 — 13 February 2023

Week 204 - 13 Feb 2023

Task 2

Task — Reshape matrix

We are given a matrix size m x n and are asked to display a new matrix with dimensions r x c with the original values from the given matrix inserted in the same order. If we can’t do that (because m x n != r x c) we are to print 0.

Analysis

This task is essentially a formatting exercise. I approached it like this:

  • Flatten the supplied matrix into a linear array
  • Display the input by formatting the linear array with the original number of columns and rows
  • Display the output by formatting the linear array with the new number of columns and rows

For the formatting to line up properly we need to know the width of the widest element, and we can conveniently do that while making the linear array.

And we need to test that the product of the row and column counts in input and output are the same, or if not to deliver Output = 0.

Try it 

Example: [[1, 2, 3], [4, 5, 6]]

r = Example: 3
c = Example: 2

Script


#!/usr/bin/perl

# Peter Campbell Smith - 2023-02-14

use v5.28;
use utf8;
use warnings;
use Time::HiRes qw(time);

# You are given a matrix (m x n) and two integers (r) and (c). Write a script to reshape the given matrix in form 
# (r x c) with the original values in the given matrix. If you can’t reshape print 0.

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge/204/2

my (@linear, $width, $x);

reshape([[1, 2, 3], [4, 5, 6]], 3, 2);
reshape([[1, 2, 3, 4, 5, 6], [11, 12, 13, 14, 15, 16]], 3, 4);
reshape([[1, 2, 3], [4, 5, 6]], 3, 7);
reshape([[1, 12, 123, 1234], [4321, 321, 21, 1]], 4, 2);

sub reshape {
    
    my ($m_old, $r_new, $c_new) = @_;
    my ($c_old, $r_old, $j, $r, $c, $x);

    # get rows and cols in original array
    $r_old = scalar(@$m_old);
    $c_old = scalar(@{$m_old->[0]});
    
    # collapse old matrix into linear array and check width needed to display
    $j = 0;
    $width = 0;
    for $r (0 .. $r_old - 1) {
        for $c (0 .. $c_old - 1) {
            $x = $m_old->[$r]->[$c];
            $width = length($x) if length($x) > $width;
            $linear[$j ++] = $x;
        }
    }
    $width ++;
    
    # show old matrix
    show("\nInput:  ", $r_old, $c_old); 
    
    # check whether transform is possible
    if ($r_old * $c_old != $r_new * $c_new) {
        say qq[\nOutput: 0\n        \$r = $r_new, \$c = $c_new];
        return;
    }
    
    # show new matrix
    show("\nOutput: ", $r_new, $c_new);
}

sub show {
    
    my ($text, $r, $c) = @_;
    my ($j, $row, $col);
    
    # display matrix
    $j = 0;
    for $col (0 .. $r - 1) {
        for $r (0 .. $c - 1) {
            $row .= sprintf("%${width}d ", $linear[$j ++]);
        }
        say qq[${text}[$row]];
        $row = '';
        $text = '        ';
    }
    say qq[        \$r = $r, \$c = $c];
}
    
    


Output


Input:  [ 1  2  3 ]
        [ 4  5  6 ]
        $r = 2, $c = 3

Output: [ 1  2 ]
        [ 3  4 ]
        [ 5  6 ]
        $r = 3, $c = 2

Input:  [  1   2   3   4   5   6 ]
        [ 11  12  13  14  15  16 ]
        $r = 2, $c = 6

Output: [  1   2   3   4 ]
        [  5   6  11  12 ]
        [ 13  14  15  16 ]
        $r = 3, $c = 4

Input:  [ 1  2  3 ]
        [ 4  5  6 ]
        $r = 2, $c = 3

Output: 0
        $r = 3, $c = 7

Input:  [    1    12   123  1234 ]
        [ 4321   321    21     1 ]
        $r = 2, $c = 4

Output: [    1    12 ]
        [  123  1234 ]
        [ 4321   321 ]
        [   21     1 ]
        $r = 4, $c = 2