# Unwrapping a matrix in a spiral pattern

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 A^{T}) can be obtained by writing the columns of A as the rows of A^{T}, or by writing the rows of A as the columns of A^{T}.

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:

- Remove the first row
- Transpose the matrix
- 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)
```