23 May 2025 | Challenge 322 |
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:
- remove any dashes from the string
- arrange the remaining string in groups of the given size separated by dashes with a possibly smaller first group
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.