-2

I would appreciate your help with a translation to Python 3 that decomposes an input array of any size into smaller square arrays of length 4.

I have tried chunks and the array functions in numpy but they are useless for this.

Here is my code in Perl that works well, but I want it to compare to Python (in efficiency).

sub make_array {
my $input = shift;
my $result;
my @parts = split '-', $input;

$result = [];

# Test for valid number of lines in inputs
my $lines = scalar @parts;
if($lines % $width){
    die "Invalid line count $lines not divisible by $width" ;
    # Or could pad here by adding an entire row of '0'.
}

# Chunk input lines into NxN subarrays
# loop across all input lines in steps of N lines

my $line_width = 0;
for (my $nn=0;$nn<$lines;$nn+=$width){

    # make a temp array to handle $width rows of input
    my @temp = (0..$width-1);
    for my $ii (0..$width-1){

        my $p = $parts[$nn+$ii];
        my $padding_needed = length($p) % $width;
        if($padding_needed != 0) { 
            print "'$p' is not divisible by correct width of $width, Adding $padding_needed zeros\n";
            for my $pp (0..$padding_needed){ 
                $p .= "0";
            }
        }
        if($line_width == 0){ 
            $line_width = length($p);
        }
        $temp[$ii] = $p;
    }
    # now process temp array left to right, creating keys
    my $chunks = ($line_width/$width);
    if($DEBUG) { print "chunks: $chunks\n"; }
    for (my $zz =0;$zz<$chunks;$zz++){
        if($DEBUG) { print "zz:$zz\n"; }
        my $key;
        for (my $yy=0;$yy<$width;$yy++){
            my $qq = $temp[$yy];
            $key .= substr($qq,$zz*$width, $width) . "-";
        }
        chop $key; # lose the trailing '-'
        if($DEBUG) { print "Key: $key\n"; }
        push @$result, $key;
    }
}        

if($DEBUG){
    print "Reformatted input:";
    print Dumper $result;
    my $count = scalar @$result;
    print "There are $count keys to check against the lookup table\n";
}
return $result;
}

As an example, I have the following 12 x 12 matrix:

000011110011
000011110011
000011110011
000011110011
000011110011
000011110011
000011110011
000011110011

and I want it decomposed into 6 square submatrices of length 4:

0000 1111 0011
0000 1111 0011
0000 1111 0011
0000 1111 0011

0000 1111 0011
0000 1111 0011
0000 1111 0011
0000 1111 0011

The original matrix comes from a file (the program should read it from a text file) in the following format:

000011110011,000011110011,000011110011,000011110011,000011110011,000011110011,000011110011,000011110011

So the program needs to split it by hyphens and take each chunk as a row of the large matrix. The 6 submatrices should come in the same input format, hence the first one would be:

0000,0000,0000,0000

The program should decompose any input matrix into square matrices of length j, say 4, if the original matrix is of size not multiple of 4 then it should disregard the remaining chunks that couldn't form a 4x4 matrix.

Several large matrices of different size could come in the original input file, with break lines as separators. For example, the original large matrix together with anothe rmatrix would look like the following in a text file:

000011110011,000011110011,000011110011,000011110011,000011110011,000011110011,000011110011,000011110011\n
0101,0101,0101,0101

and retrieve the 2 sets of subarrays, one of 6 arrays of 4x4 and a single one of 4x4 for the second one. If you solve it for the single case is of course fine.

  • 1
    On SO, you're generally expected to have worked on a task yourself, and to come when you get stuck on something. Simply handing out an assignment tends to have a bad reception. – millimoose Mar 31 '13 at 20:12
  • `"I need a program in Python 3"`, that's not gonna work here. Show us what you've tried? – Ashwini Chaudhary Mar 31 '13 at 20:12
  • I have tried chunks which only cuts strings, I have tried the array functions in numpy but are useless for this. I also have implementations in Perl and other languages. Here the Perl one in case it helps for the Python one: – user2230059 Mar 31 '13 at 20:19
  • sorry, it was my first post, I hope you don't pile on me, and thanks for any help. – user2230059 Mar 31 '13 at 20:24

1 Answers1

1

This is easy with numpy. Suppose we have a 12x12 array;

In [1]: import numpy as np

In [2]: a = np.arange(144).reshape([-1,12])

In [3]: a
Out[3]: 
array([[  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11],
       [ 12,  13,  14,  15,  16,  17,  18,  19,  20,  21,  22,  23],
       [ 24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35],
       [ 36,  37,  38,  39,  40,  41,  42,  43,  44,  45,  46,  47],
       [ 48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59],
       [ 60,  61,  62,  63,  64,  65,  66,  67,  68,  69,  70,  71],
       [ 72,  73,  74,  75,  76,  77,  78,  79,  80,  81,  82,  83],
       [ 84,  85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95],
       [ 96,  97,  98,  99, 100, 101, 102, 103, 104, 105, 106, 107],
       [108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119],
       [120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131],
       [132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143]])

To select the top-left 4x4 array, use slicing:

In [4]: a[0:4,0:4]
Out[4]: 
array([[ 0,  1,  2,  3],
       [12, 13, 14, 15],
       [24, 25, 26, 27],
       [36, 37, 38, 39]])

The right-bottom sub-array is:

In [7]: a[8:12,8:12]
Out[7]: 
array([[104, 105, 106, 107],
       [116, 117, 118, 119],
       [128, 129, 130, 131],
       [140, 141, 142, 143]])

You can guess the rest...

Roland Smith
  • 42,427
  • 3
  • 64
  • 94