The Bear's Den

Enter at your own risk

Nice Integers

Task 1: Counter Integers

Submitted by: Mohammad Sajid Anwar


You are given a string containing only lower case English letters and digits.

Write a script to replace every non-digit character with a space and then return all the distinct integers left.

Example 1

Input: $str = "the1weekly2challenge2"
Output: 1, 2

2 is appeared twice, so we count it one only.

Example 2

Input: $str = "go21od1lu5c7k"
Output: 21, 1, 5, 7

Example 3

Input: $str = "4p3e2r1l"
Output: 4, 3, 2, 1

Solution

Extracting all substrings that consist of digits only and pick the unique values thereof. Works with any characters.

use strict;
use warnings;
use List::Util 'uniqint';

sub count_int {
    uniqint shift =~ /\d+/g;
}

See the full solution to task 1.

Task 2: Nice String

Submitted by: Mohammad Sajid Anwar


You are given a string made up of lower and upper case English letters only.

Write a script to return the longest substring of the give string which is nice. A string is nice if, for every letter of the alphabet that the string contains, it appears both in uppercase and lowercase.

Example 1

Input: $str = "YaaAho"
Output: "aaA"

Example 2

Input: $str = "cC"
Output: "cC"

Example 3

Input: $str = "A"
Output: ""

No nice string found.

Solution

Solving the task in two steps:

  1. Find all nice substrings.
  2. Find the longest nice substring.

Any character that is not a letter appearing in upper and lower case cannot be part of a nice substring. Therefore the string may be split into parts separated by any of these characters. If the split result has only one nonempty part, all the nice letters are contained within this part and therefore it is nice. Otherwise the nice letters may be distributed over different parts and each part has to be split again - a case for recursion.

We build a set of all lower case letters in the string and a second set of all upper case letters converted to lower case. The intersection of these sets is the complement of the split character class. An empty intersection signals “no nice substrings”. Otherwise we build a bracketed character class as the complement of the intersection and use a repetition of one or more such characters as a split expression.

Returning the (first) longest found nice substring.

Works with any characters.

use strict;
use warnings;
use Set::Scalar;
use List::UtilsBy 'max_by';
use experimental 'signatures';

sub split_nice ($str) {
    my $nice = Set::Scalar->new($str =~ /\p{Ll}/g) *
        Set::Scalar->new(map lc, $str =~ /\p{Lu}/g);
    return () if $nice->is_null;
    my @parts = grep $_, split qr{[^ @$nice]+}ixx, $str;
    @parts == 1 ? @parts : map split_nice($_), @parts;
}

sub nice_string ($str) {
    (max_by {length} split_nice($str)) // '';
}

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.