DEV Community

Simon Green
Simon Green

Posted on

Weekly Challenge: Maximum Encryption

Weekly Challenge 358

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. It's a great way for us all to practice some coding.

Challenge, My solutions

Task 1: Max Str Value

Task

You are given an array of alphanumeric string, @strings.

Write a script to find the max value of alphanumeric string in the given array. The numeric representation of the string, if it comprises of digits only otherwise length of the string.

My solution

This task can be achieved in a single line in both Python and Perl, while still maintaining readability. For the Python solution I use list comprehension to convert each string into an integer (if it is all digits) or the length of string (if it isn't). This is wrapped around the max function to return maximum (largest) of these values.

def max_string_value(input_strings: list) -> int:
    return max(int(s) if s.isdigit() else len(s) for s in input_strings)
Enter fullscreen mode Exit fullscreen mode

Not to out-shinned, Perl can achieve similar functionality by using the map function, converting each string into its numeric representation or its length. Perl doesn't have a built-in max function, but it is available from the List::Util package.

sub main (@input_strings) {
    say max( map { /^\d+$/ ? $_ : length($_) } @input_strings );
}
Enter fullscreen mode Exit fullscreen mode

Examples

$ ./ch-1.py "123" "45" "6"
123

$ ./ch-1.py "abc" "de" "fghi"
4

$ ./ch-1.py "0012" "99" "a1b2c"
99

$ ./ch-1.py "x" "10" "xyz" "007"
10

$ ./ch-1.py "hello123" "2026" "perl"
2026
Enter fullscreen mode Exit fullscreen mode

Task 2: Encrypted String

Task

You are given a string $str and an integer $int.

Write a script to encrypt the string using the algorithm - for each character $char in $str, replace $char with the $int th character after $char in the alphabet, wrapping if needed and return the encrypted string.

My solution

For this task, I start by setting $int (called i in Python as int is a reserved word) to be the modulus (remainder) of 26. If that value is 0, I return the original string as no encryption is required.

def encrypted_string(input_string: str, i: int) -> str:
    i = i % 26

    if i == 0:
        return input_string
Enter fullscreen mode Exit fullscreen mode

The next step is creating a mapping table. I start with the variable old_letters that has all the lower case letters of the English alphabet. I create a new_letters string by slicing the old_letters string at the appropriate point. I then double the length of each string by adding the upper case equivalent string. Finally, I use dict(zip()) to convert the strings to a dictionary where the key is the original letter and the value is the new letter.

    old_letters = string.ascii_lowercase
    new_letters = old_letters[i:] + old_letters[:i]
    old_letters += old_letters.upper()
    new_letters += new_letters.upper()
    mapping = dict(zip(old_letters, new_letters))
Enter fullscreen mode Exit fullscreen mode

The final step is to loop through each character and use the mapping dictionary to replace the letter, or use the original character if it is not found (numbers, spaces, punctuation characters, etc).

    return "".join(mapping.get(char, char) for char in input_string)
Enter fullscreen mode Exit fullscreen mode

The Perl code follows the same logic. It uses the splice method to create the new_letters variable, and both old_letters and new_letters are arrays. The mesh function also comes from the List::Util package. Perl will automatically convert a flat list to key/value pairs in the mapping hash.

sub main ( $input_string, $i ) {
    $i %= 26;

    if ( $i == 0 ) {
        say $input_string;
        return;
    }

    my @old_letters = my @new_letters = ( "a" .. "z" );
    push @new_letters, splice( @new_letters, 0, $i );

    push @old_letters, map { uc } @old_letters;
    push @new_letters, map { uc } @new_letters;
    my %mapping = mesh \@old_letters, \@new_letters;


    say join "", map { $mapping{$_} // $_ } split //, $input_string;
Enter fullscreen mode Exit fullscreen mode

Examples

$ ./ch-2.py abc 1
bcd

$ ./ch-2.py xyz 2
zab

$ ./ch-2.py abc 27
bcd

$ ./ch-2.py hello 5
mjqqt

$ ./ch-2.py perl 26
perl
Enter fullscreen mode Exit fullscreen mode

Top comments (0)