DEV Community

Simon Green
Simon Green

Posted on

Weekly Challenge: It's all about the translation

Weekly Challenge 364

Each week Mohammad S. Anwar sends out The Weekly Challenge, a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. Unless otherwise stated, Copilot (and other AI tools) have NOT been used to generate the solution. It's a great way for us all to practice some coding.

Challenge, My solutions

Task 1: Decrypt String

Task

You are given a string formed by digits and #. Write a script to map the given string to English lowercase characters following the given rules.

  • Characters a to i are represented by 1 to 9 respectively.
  • Characters j to z are represented by 10# to 26# respectively.

My solution

This task calls for regular expressions to be used. Both Python and Perl allow call back functions in the replacement section (i.e. you can call a function to find the new string).

For the Python solution, I have a (callback) function called replace_digits. It takes a Match object as input and returns a string.

def replace_digits(m: re.Match) -> str:
    c = m.group(0)
    return chr(96 + int(c[:2]))
Enter fullscreen mode Exit fullscreen mode

The variable c has the matching string (either a single digit or two digits (10-26) followed by a hash character. Things to note:

  • c[:2] will remove the hash if it is present.
  • int(...) will convert this into a number
  • chr(...) will turn this into a letter of the alphabet. The ASCII code for the letter a is 97.

The main function checks that the input is valid. It then uses re.sub to perform the substitution in the replace_digits function.

def decrypt_string(input_string: str) -> str:
    if not re.search(r'^(1\d#|2[0-6]#|\d)*$', input_string):
        raise ValueError("String not in expected format")

    return re.sub(r'(1\d#|2[0-6]#|\d)', replace_digits, input_string)
Enter fullscreen mode Exit fullscreen mode

The Perl solution follows the same logic, except that the replacement value can be code (not just a function call). This negates the need for a separate function. The substr function is used to remove the hash character.

sub main ($input_string) {
    if ( $input_string !~ /^(1\d#|2[0-6]#|\d)*$/ ) {
        die "String not in expected format\n";
    }

    my $output_string = $input_string;
    $output_string =~ s/(1\d#|2[0-6]#|\d)/chr(96 + substr($1,0,2))/eg;
    say $output_string;
}
Enter fullscreen mode Exit fullscreen mode

In the regular expression, /e indicates that the replacement value is a expression (as opposed to the literal string), and /g means to run the regular expression globally (on all occurrences).

Examples

$ ./ch-1.py 10#11#12
jkab

$ ./ch-1.py 1326#
acz

$ ./ch-1.py 25#24#123
yxabc

$ ./ch-1.py 20#5
te

$ ./ch-1.py 1910#26#
aijz
Enter fullscreen mode Exit fullscreen mode

Task 2: Goal Parser

Task

You are given a string, $str.

Write a script to interpret the given string using Goal Parser. The Goal Parser interprets G as the string G, () as the string o, and (al) as the string al. The interpreted strings are then concatenated in the original order.

My solution

For this task, I use a regular expression to check that the input_string is in the expected format. I then use the replace function to change the string to the required output.

def good_parser(input_string: str) -> str:
    if not re.search(r'^(G|\(\)|\(al\))*$', input_string):
        raise ValueError("Unexpected input received")

    return input_string.replace('()', 'o').replace('(al)', 'al')
Enter fullscreen mode Exit fullscreen mode

Perl doesn't have a replace function, so I use a regular expression to perform the replacement.

sub main ($input_string) {
    if ($input_string !~ /^(G|\(\)|\(al\))*$/) {
        die "Unexpected input received\n;"
    }

    my $output_string = $input_string;
    $output_string =~s/\(\)/o/g;
    $output_string =~ s/\(al\)/al/g;

    say $output_string;
}
Enter fullscreen mode Exit fullscreen mode

Examples

Parentheses have special meaning in bash, so quotes are used to handle this.

$ ./ch-2.pl "G()(al)"
Goal

$ ./ch-2.pl "G()()()()(al)"
Gooooal

$ ./ch-2.pl "(al)G(al)()()"
alGaloo

$ ./ch-2.pl "()G()G"
oGoG

$ ./ch-2.pl "(al)(al)G()()"
alalGoo
Enter fullscreen mode Exit fullscreen mode

Top comments (0)