Perl Weekly Challenge 245: Sort Language

These are some answers to the Week 245, Task 1, of the Perl Weekly Challenge organized by Mohammad S. Anwar.

Spoiler Alert: This weekly challenge deadline is due in a few days from now (on December 3, 2023 at 23:59). This blog post provides some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.

Task 1: Sort Language

You are given two arrays of languages and its popularity.

Write a script to sort the language based on popularity.

Example 1

Input: @lang = ('perl', 'c', 'python')
       @popularity = (2, 1, 3)
Output: ('c', 'perl', 'python')

Example 2

Input: @lang = ('c++', 'haskell', 'java')
       @popularity = (1, 3, 2)
Output: ('c++', 'java', 'haskell')

Sort Language in Raku

On reading the assignment, I initially thought for a minute or so that it would be quite easy to sort one array (@lang) in accordance with the values of another one (@popularity). But it immediately came to my mind that, in fact, you don't even need to actually sort anything. You can just use the second array (@popularity) as an index slice for the first one (@lang), so that we avoid the algorithmic complexity of a sort procedure and return directly the languages in the proper order. The sort-lang subroutine is thus a simple one-liner. Note that the input popularity is given with values starting at 1, whereas array or list indices start at 0, so we need the map {$_ - 1} expression to convert popularities into array indices.

sub sort-lang (@lang, @pop) {
    return ~ @lang[map {$_ - 1}, @pop];

my @tests = 
    { lang => <perl c python>, pop => (2, 1, 3)},
    { lang => <c++ haskell java>, pop  => (1, 3, 2)};

for @tests -> %test {
    printf "%-20s", "%test<lang> => ";
    say sort-lang %test<lang>, %test<pop>;

This program displays the following output:

$ raku ./sort-language.raku
perl c python =>    c perl python
c++ haskell java => c++ java haskell

Sort Language in Perl

This is a port to Perl of the Raku program above, and we are using array slices just like in the Raku implementation. Please refer to the previous section for any explanation.

use strict;
use warnings;
use feature 'say';

sub sort_lang {
    my @lang = @{$_[0]};
    my @pop  = @{$_[1]};
    return join " ",  @lang[map {$_ - 1} @pop];

my @tests = 
    ({ lang => [<perl c python>],    pop => [2, 1, 3]},
     { lang => [<c++ haskell java>], pop => [1, 3, 2]});

for my $test (@tests) {
    printf "%-22s", "@{$test->{lang}} => ";
    say sort_lang $test->{lang}, $test->{pop};

This program displays the following output:

$ perl ./
perl c python =>      c perl python
c++ haskell java =>   c++ java haskell

Wrapping up

The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check and make sure you answer the challenge before 23:59 BST (British summer time) on December 10, 2023. And, please, also spread the word about the Perl Weekly Challenge if you can.

Leave a comment

About laurent_r

user-pic I am the author of the "Think Perl 6" book (O'Reilly, 2017) and I blog about the Perl 5 and Raku programming languages.