Perl Weekly Challenge 040: Multiple Arrays & Sort SubList

Multiple Arrays

You are given two or more arrays. Write a script to display values of each list at a given index.

For example:

Array 1: [ I L O V E Y O U ]
Array 2: [ 2 4 0 3 2 0 1 9 ]
Array 3: [ ! ? £ $ % ^ & * ]

We expect the following output:

I 2 !
L 4 ?
O 0 £
V 3 $
E 2 %
Y 0 ^
O 1 &
U 9 *

The pound sign is not part of the standard ASCII, so we’ll need to properly encode it. The use utf8; clause tells perl that the script itself contains UTF-8 encoded characters, the binmode function sets the encoding for the given filehandle, i.e. standard output.

We can now iterate over the indices of the arrays and print the element at the same index from each array. The inner loop over the arrays is expressed as a map:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
use utf8;

binmode *STDOUT, ':encoding(UTF-8)';

my @arrays = ([qw[ I L O V E Y O U ]],
              [qw[ 2 4 0 3 2 0 1 9 ]],
              [qw[ ! ? £ $ % ^ & * ]]);

for my $i (0 .. $#{ $arrays[0] }) {
    say join ' ', $i, map $_->[$i], @arrays;
}

Sort SubList

You are given a list of numbers and set of indices belong to the list. Write a script to sort the values belongs to the indices.

For example:

List: [ 10, 4, 1, 8, 12, 3 ]
Indices: 0, 2, 5

We would sort the values at indices 0, 2 and 5 i.e. 10, 1 and 3. Final List would look like below:

List: [ 1, 4, 3, 8, 12, 10 ]

In Perl, it’s easy to extract a sublist or subarray with given indices. It’s called a slice and we’ve discussed slices in PWC 034.

One aspect of slices wasn’t mentioned in the linked article, though. They can be used in the lvalue context, i.e. they can be assigned to. Therefore, we can extract the sublist at the given indices, sort it, and assign the result back to the original positions in one assignment:

#!/usr/bin/perl
use warnings;
use strict;

my @list = (10, 4, 1, 8, 12, 3);
my @indices = (0, 2, 5);

my @sorted = @list;
@sorted[@indices] = sort { $a <=> $b } @sorted[@indices];

my @expected = (1, 4, 3, 8, 12, 10);

"@sorted" eq "@expected"
    or die "Got:      @sorted\nExpected: @expected\n";

sort sorts asciibetically by default, we need to specify the numeric comparison subroutine { $a <=> $b } to sort 10 after 3.

Leave a comment

About E. Choroba

user-pic I blog about Perl.