The Bear's Den

Enter at your own risk

Group Ranking

Task 1: String Format

Submitted by: Mohammad Sajid Anwar


You are given a string and a positive integer.

Write a script to format the string, removing any dashes, in groups of size given by the integer. The first group can be smaller than the integer but should have at least one character. Groups should be separated by dashes.

Example 1

Input: $str = "ABC-D-E-F", $i = 3
Output: "ABC-DEF"

Example 2

Input: $str = "A-BC-D-E", $i = 2
Output: "A-BC-DE"

Example 3

Input: $str = "-A-B-CD-E", $i = 4
Output: "A-BCDE"

Solution

There are two subtasks:

Removing any existing dashes can easily done with the tr operator.

Then we globally match a nonempty leading substring with a maximum length of $i such that the remaining string consists of groups having the given size and join all matched parts with dashes.

use strict;
use warnings;
use experimental 'signatures';

sub string_format ($str, $i) {
    join '-', $str =~ tr/-//dr =~ /^.{1,$i}(?=(?:.{$i})*+$)|.{$i}/g;
}

See the full solution to task 1.

Task 2: Rank Array

Submitted by: Mohammad Sajid Anwar


You are given an array of integers.

Write a script to return an array of the ranks of each element: the lowest value has rank 1, next lowest rank 2, etc. If two elements are the same then they share the same rank.

Example 1

Input: @ints = (55, 22, 44, 33)
Output: (4, 1, 3, 2)

Example 2

Input: @ints = (10, 10, 10)
Output: (1, 1, 1)

Example 3

Input: @ints = (5, 1, 1, 4, 3)
Output: (4, 1, 1, 3, 2)

Solution

Ranking is a recurring theme in the Weekly Challenge, see task 2 from week 9, “Rank Score” or “Count Smaller”.

The ranking as required in this task may be found using PDL’s enumvecg method on a sorted list.

Therefore we perform an index sort, enumerate the sorted values as dummy vectors and assign the ranks in the original order.

Finally the ranks need to be adjusted by 1.

use strict;
use warnings;
use PDL;
use PDL::NiceSlice;

sub rank_array {
    my $ints = long @_;
    my $si = $ints->qsorti;
    my $rank = zeroes $ints;
    $rank($si) .= $ints($si)->dummy(0)->enumvecg;
    $rank + 1;
}

See the full solution to task 2.


If you have a question about this post or if you like to comment on it, feel free to open an issue in my github repository.