aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJörg Sommrey <28217714+jo-37@users.noreply.github.com>2020-11-23 15:04:59 +0100
committerJörg Sommrey <28217714+jo-37@users.noreply.github.com>2020-11-25 17:36:41 +0100
commita6d83a70e13595d5d1f697b60164384f8129a197 (patch)
tree77a878d0368d1698cf7477e143f0db1f04c9d657
parent0de3c77ff03f11cff94be7f91ad134bcf9ffcb36 (diff)
downloadperlweeklychallenge-club-a6d83a70e13595d5d1f697b60164384f8129a197.tar.gz
perlweeklychallenge-club-a6d83a70e13595d5d1f697b60164384f8129a197.tar.bz2
perlweeklychallenge-club-a6d83a70e13595d5d1f697b60164384f8129a197.zip
Solution to task 2
-rwxr-xr-xchallenge-088/jo-37/perl/ch-2.pl87
1 files changed, 87 insertions, 0 deletions
diff --git a/challenge-088/jo-37/perl/ch-2.pl b/challenge-088/jo-37/perl/ch-2.pl
new file mode 100755
index 0000000000..7eb15b6f5d
--- /dev/null
+++ b/challenge-088/jo-37/perl/ch-2.pl
@@ -0,0 +1,87 @@
+#!/usr/bin/perl
+
+use 5.012;
+use PDL;
+use Test2::V0 '!float';
+use experimental 'postderef';
+
+{
+ # Instructions for the unrolling engine:
+ # - edge (as slice arg)
+ # - remaining matrix (as slice arg)
+ # - affected dimension (row or column)
+ # by direction.
+ my @instr = (
+ ['X,(0)', 'X,1:-1', 1], # first row, east
+ ['(-1),X', '0:-2,X', 0], # last column, south
+ ['-1:0,(-1)', 'X,0:-2', 1], # last row, west
+ ['(0),-1:0', '1:-1,X', 0]); # first column, north
+
+ # Unroll given matrix, i.e. return the elements as a 1-d list in
+ # spiral form.
+ sub unroll {
+ # Input matrix, starting direction and result.
+ my ($m, $dir, $unrolled) = (long(shift), 0, PDL->null);
+
+ say $m;
+ die "not a matrix" unless $m->ndims == 2;
+
+ while (1) {
+ # Get the instructions.
+ my ($edge, $remaining, $dim) = $instr[$dir]->@*;
+
+ # Append current edge to the result.
+ $unrolled = $unrolled->append($m->slice($edge));
+
+ # Stop if the current edge was the last remaining dimension.
+ last if $m->dim($dim) == 1;
+
+ # Take the remaining matrix.
+ $m = $m->slice($remaining);
+
+ # Switch direction.
+ $dir = ($dir + 1) % 4;
+ }
+
+ say $unrolled;
+ $unrolled->unpdl;
+ }
+}
+
+# Test cases by ending direction and number of trailing elements.
+is unroll(sequence(long, 3, 3) + 1),
+ [1, 2, 3, 6, 9, 8, 7, 4, 5], 'east-1 (Example 1)';
+
+is unroll(sequence(long, 4, 3) + 1),
+ [1, 2, 3, 4, 8, 12, 11, 10, 9, 5, 6, 7], 'east-2';
+
+is unroll(sequence(long, 3, 4) + 1),
+ [1, 2, 3, 6, 9, 12, 11, 10, 7, 4, 5, 8], 'south-1';
+
+is unroll(sequence(long, 3, 5) + 1),
+ [1, 2, 3, 6, 9, 12, 15, 14, 13, 10, 7, 4, 5, 8, 11], 'south-2';
+
+is unroll(sequence(long, 4, 4) + 1),
+ [1, 2, 3, 4, 8, 12, 16, 15, 14, 13, 9, 5, 6, 7, 11, 10],
+ 'west-1 (Example 2)';
+
+is unroll(sequence(long, 5, 4) + 1),
+ [1, 2, 3, 4, 5, 10, 15, 20, 19, 18, 17, 16, 11, 6, 7, 8, 9, 14, 13, 12],
+ 'west-2';
+
+is unroll(sequence(long, 4, 5) + 1),
+ [1, 2, 3, 4, 8, 12, 16, 20, 19, 18, 17, 13, 9, 5, 6, 7, 11, 15, 14, 10],
+ 'north-1';
+
+is unroll(sequence(long, 4, 6) + 1),
+ [1, 2, 3, 4, 8, 12, 16, 20, 24, 23, 22, 21, 17, 13, 9,
+ 5, 6, 7, 11, 15, 19, 18, 14, 10], 'north-2';
+
+# other tests
+is unroll([[1, 2], [3, 4]]), [1, 2, 4, 3], 'non-piddle arg';
+is unroll([[1, 2]]), [1, 2], 'single row';
+is unroll([[1],[2]]), [1, 2], 'single column';
+is unroll([[1]]), [1], 'single element';
+like dies {unroll [1]}, qr/^not a matrix/, 'not a matrix';
+
+done_testing;