This is my solution to a Programming Praxis exercise that was posted a while back.

Given a potentially non-square matrix, write a function that returns its elements in a spiral pattern.

For example, given the matrix:

[  [ 1,  2,  3,  4],
[ 5,  6,  7,  8],
[ 9, 10, 11, 12],
[13, 14, 15, 16],
[17, 18, 19, 20],
]


The final result would be:

[1, 2, 3, 4, 8, 12, 16, 20, 19, 18, 17, 13, 9, 5, 6, 7, 11, 15, 14, 10]


I imagine there are many ways to solve this problem, but for me it only clicked once I removed the first row of elements (i.e. $matrix[0]). Here is the matrix with the first row removed: [ [ 5, 6, 7, 8], [ 9, 10, 11, 12], [13, 14, 15, 16], [17, 18, 19, 20], ]  Now think about what elements you need to get next. That would be [8, 12, 16, 20] (from solution above). Is there a series of operations you could perform that gives you the [8, 12, 16, 20] where the first row previously was. Or more concisely put, what operations will make [8, 12, 16, 20] the first row in the matrix? ### Transpose of a matrix The transpose of a matrix A (denoted AT) can be obtained by writing the columns of A as the rows of AT, or by writing the rows of A as the columns of AT. If we transpose the matrix above, we get this: [ [ 5, 9, 13, 17 ], [ 6, 10, 14, 18 ], [ 7, 11, 15, 19 ], [ 8, 12, 16, 20 ], ]  Now the elements we want are in the last row of the matrix, we can get them to the top by reversing the matrix. Reversal of the transposed matrix: [ [ 8, 12, 16, 20 ], [ 5, 9, 13, 17 ], [ 6, 10, 14, 18 ], [ 7, 11, 15, 19 ], ]  Now we can repeat this process to get our spiral: 1. Remove the first row 2. Transpose the matrix 3. Reverse the matrix Implementation in Perl below: #!/usr/bin/perl use strict; use warnings; use Data::Dumper; sub transpose { my ($matrix) = @_;

my $transposed = []; for my$i (0 .. $#$matrix) {
for my $j (0 ..$#{ $matrix->[0] }) {$transposed->[$j][$i] = $matrix->[$i][$j]; } } return$transposed;
}

sub unwrap {
my ($matrix) = @_; my @spiral; while ($matrix && @$matrix ) { push @spiral, map { @$_ } shift @$matrix; # transpose and reverse$matrix = [reverse @{transpose($matrix)}]; } return \@spiral; } my$matrix = [
[qw( 1  2  3  4)],
[qw( 5  6  7  8)],
[qw( 9 10 11 12)],
[qw(13 14 15 16)],
[qw(17 18 19 20)],
];

print Dumper unwrap(\$matrix)