07 March 2025 | Challenge 311 |
Flip Groups
Task 1: Upper Lower
Submitted by: Mohammad Sajid Anwar
You are given a string consists of english letters only.
Write a script to convert lower case to upper and upper case to lower in the given string.
Example 1
Input: $str = "pERl"
Output: "PerL"
Example 2
Input: $str = "rakU"
Output: "RAKu"
Example 3
Input: $str = "PyThOn"
Output: "pYtHoN"
Solution
In a global substitution operation we search for single lower or upper case letters and replace them with the opposite case. Using Unicode properties to identify lower and upper case letters. This approach is not limited to English letters.
use strict;
use warnings;
use experimental 'signatures';
sub xc ($str) {
$str =~ s/(\p{Lu})|(\p{Ll})/$1 ? lc($1) : uc($2)/egr
}
See the full solution to task 1.
Task 2: Group Digit Sum
Submitted by: Mohammad Sajid Anwar
You are given a string, $str
, made up of digits, and an integer, $int
, which is less than the length of the given string.
Write a script to divide the given string into consecutive groups of size $int
(plus one for leftovers if any). Then sum the digits of each group, and concatenate all group sums to create a new string. If the length of the new string is less than or equal to the given integer then return the new string, otherwise continue the process.
Example 1
Input: $str = "111122333", $int = 3
Output: "359"
Step 1: "111", "122", "333" => "359"
Example 2
Input: $str = "1222312", $int = 2
Output: "76"
Step 1: "12", "22", "31", "2" => "3442"
Step 2: "34", "42" => "76"
Example 3
Input: $str = "100012121001", $int = 4
Output: "162"
Step 1: "1000", "1212", "1001" => "162"
Solution
There is a subtlety in this task: We are given a string holding decimal digits, not an integer. Therefore we should not assume the number represented by the string fits into any “standard” data type.
Split the given string into a 1-d ndarray made of its digits.
Transform the vector into a $int x M
matrix, summarize over its rows and convert the sums into digits again until the resulting vector does not exceed the given length.
Finally create the result (as a string) by joining its digits.
use strict;
use warnings;
use PDL;
use experimental 'signatures';
sub group_digit_sum ($str, $len) {
my $n = long split //, $str;
$n = long map split(//, $_),
$n->reshape($len, ceil $n->dim(0) / $len)->sumover->list
while $n->dim(0) > $len;
join '', $n->list;
}
Consider a string consisting of 320 9
s, $str = '9' x 320
and $int = 40
.
There are 8 groups of 40 digits having a digit sum of 360
each, leading to a result of '360' x 8'
.
Here we have to make sure, we don’t loose any digits from the input string and produce all 24 digits in the output string.
To avoid typing 320 9
s:
$ perl -E 'do "./ch-2.pl"; say group_digit_sum("9" x 320, 40)'
360360360360360360360360
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.