TL;DR

The solution to task #2 of the Perl Weekly Challenge for this week, and additional reflections.

In last post Leader element I shared a trivial thought about how the Perl Weekly Challenge tasks can be a good excercise for thinking about the problems beyond providing a quick answer for them.

This is also the case for the task #2 in this week’s challenge:

You are given array @A containing positive numbers and @B containing one or more indices from the array @A.

Write a script to left rotate @A so that the number at the first index of @B becomes the first element in the array. Similary, left rotate @A again so that the number at the second index of @B becomes the first element in the array.

My solution is pretty straightforward (most is scaffolding for testing):

`````` 1 #!/usr/bin/env perl
2 use 5.024;
3 use warnings;
4 use experimental qw< postderef signatures >;
5 no warnings qw< experimental::postderef experimental::signatures >;
6
7 sub shift_left_by (\$n, @A) { (@A[\$n..\$#A], @A[0..(\$n-1)]) }
8 sub shift_left (\$A, \$B) { map { [shift_left_by(\$_, \$A->@*)] } \$B->@* }
9
10 for my \$test (
11    [
12       'first test',
13       [qw< 10 20 30 40 50 >],
14       [qw< 3 4 >],
15    ],
16    [
17       'second test',
18       [qw< 7 4 2 6 3 >],
19       [qw< 1 3 4 >]
20    ],
21 ) {
22    my (\$title, \$A, \$B) = \$test->@*;
23    say {*STDERR} \$title;
24    say {*STDOUT} '[', join(', ', \$_->@*), ']' for shift_left(\$A, \$B);
25 }
``````

Function `shift_left` iterates over the indexes in `\$B` (which is a reference to `@B`) and calls the actual left-shifting function `shift_left_by`. This, in turn, takes the relevant parts out of the array and arranges them as requested.

There’s a lot that might be discussed, e.g.:

• this solution assumes that it’s OK to create copies of the `@A` array around, which should be double checked;
• it might be interesting to understand whether a solution that “starts from the previous iteration” might go better (e.g. speed-wise) with respect to this, especially if we’re not allowed to make copies of `@A` but have to do the shifting in-place (in this case, we would have to do some modulo `scalar(@A)` arithmetic over the indices in `@B`);
• what should the functions/script do in case of wrong inputs (e.g. an index in `@B` that is not present in `@A`).

Cheers!

Comments? Octodon, , GitHub, Reddit, or drop me a line!