site.base_url }}/">The Bear's Den -->

The Bear's Den

Enter at your own risk

Replacing the Broken Keys

Task 1: Broken Keys

Submitted by: Mohammad Sajid Anwar


You are given a sentence, $sentence and list of broken keys @keys.

Write a script to find out how many words can be typed fully.

Example 1

Input: $sentence = "Perl Weekly Challenge", @keys = ('l', 'a')
Output: 0

Example 2

Input: $sentence = "Perl and Raku", @keys = ('a')
Output: 1

Only Perl since the other word two words contain 'a' and can't be typed fully.

Example 3

Input: $sentence = "Well done Team PWC", @keys = ('l', 'o')
Output: 2

Example 4

Input: $sentence = "The joys of polyglottism", @keys = ('T')
Output: 2

Solution

A word is typeable, if it does not contain any letters from one of the broken keys independent of its case. Thus we may create a character class containing the complement of the broken ones and match strings that completely consists of typeable characters.

When interpolating the dereferenced array ref of broken keys, we ignore the inserted blanks using the /xx modifier that is available in perl v5.26.

Finally, the generated regex is applied via grep to each word from the string. In scalar context, this gives the requested word count.

use v5.26;
use warnings;

sub broken_keys {
    my $typeable = qr{^[^@{+shift}]+$}ixx;

    grep /$typeable/, split /\s+/, shift;
}

See the full solution to task 1.

Task 2: Replace Digits

Submitted by: Mohammad Sajid Anwar


You are given an alphanumeric string, $str, where each character is either a letter or a digit.

Write a script to replace each digit in the given string with the value of the previous letter plus (digit) places.

Example 1

Input: $str = 'a1c1e1'
Ouput: 'abcdef'

shift('a', 1) => 'b'
shift('c', 1) => 'd'
shift('e', 1) => 'f'

Example 2

Input: $str = 'a1b2c3d4'
Output: 'abbdcfdh'

shift('a', 1) => 'b'
shift('b', 2) => 'd'
shift('c', 3) => 'f'
shift('d', 4) => 'h'

Example 3

Input: $str = 'b2b'
Output: 'bdb'

Example 4

Input: $str = 'a16z'
Output: 'abgz'

Solution

There are some cases not covered by the description or the examples:

To address these cases, some additional rules are established:

We use an array @d2a and a hash %a2i to convert digits to alpha and alpha to indices respectively, that are pre-initialized in a BEGIN block.

use strict;
use warnings;

{
    my (@d2a, %a2i);
    BEGIN {
        @d2a = ('A' .. 'Z', 'a' .. 'z');
        @a2i{@d2a} = (0 .. $#d2a);
    }

    sub replace_digits {
        my $prev = 0;

        join '', map /\d/ ? $d2a[($prev + $_) % @d2a] :
            do {$prev = $a2i{$_} // die "Illegal char '$_'"; $_},
            split //, shift;
    }

}

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.