The Bear's Den

Enter at your own risk

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 9s, $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 9s:

$ 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.