DEV Community

Simon Green
Simon Green

Posted on

Weekly Challenge: The race car has rhythm

Weekly Challenge 380

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: Sum of Frequencies

Task

You are given a string consisting of English letters.

Write a script to find the vowel and consonant with maximum frequency. Return the sum of two frequencies.

My solution

I start this task by creating a frequency dict (hash in Perl) called freq using the Counter function from the collections module. I create two variables max_vowels and max_consonants with both set to zero.

I loop through the freq dict, and update the one of the maximum variables if it is larger than the existing value. I finish by returning the sum of these two variables.

from collections import Counter

def sum_of_frequencies(input_string: str) -> int:
    freq = Counter(input_string.lower())

    max_vowels = 0
    max_consonants = 0
    for letter, count in freq.items():
        if letter in {"a", "e", "i", "o", "u"}:
            if count > max_vowels:
                max_vowels = count
        else:
            if count > max_consonants:
                max_consonants = count

    return max_vowels + max_consonants
Enter fullscreen mode Exit fullscreen mode

As Perl does not have an equivalent of the Counter function, I create the freq hash manually. The rest of the code follows the same logic.

sub main ($input_string) {
    my %freq = ();
    $freq{$_}++ foreach ( split //, $input_string );

    my $max_vowels     = 0;
    my $max_consonants = 0;
    while ( my ( $letter, $count ) = each %freq ) {
        if ( index( "aeiou", $letter ) != -1 ) {
            if ( $count > $max_vowels ) {
                $max_vowels = $count;
            }
        }
        else {
            if ( $count > $max_consonants ) {
                $max_consonants = $count;
            }
        }
    }

    say $max_vowels + $max_consonants;

}
Enter fullscreen mode Exit fullscreen mode

Examples

$ ./ch-1.py banana
5

$ ./ch-1.py teestett
7

$ ./ch-1.py aeiouuaa
3

$ ./ch-1.py rhythm
2

$ ./ch-1.py x
1
Enter fullscreen mode Exit fullscreen mode

Task 2: Reverse Degree

Task

You are given a string.

Write a script to find the reverse degree of the given string.

For each character, multiply its position in the reversed alphabet (a = 26, b = 25, …, z = 1) with its position in the string. Sum these products for all characters in the string to get the reverse degree.

My solution

Both Python and Perl has the ord function which returns the integer Unicode code point value to for the supplied character. For the lower case English alphabet, 97 is a while 122 is the letter z.

For this task, I start by checking that the supplied string only contains English letters.

import re
def reverse_degree(input_string: str) -> int:
    if not re.search("^[a-zA-Z]*$", input_string):
        raise ValueError("String must only contain English letters")
Enter fullscreen mode Exit fullscreen mode

I then generate a list (array in Perl) called number that has the revered alphabet number of each letter in input_string. Rather than relying on the character after z in the ASCII table being {, I use ord("z") + 1 to get the correct values.

    numbers = [ord("z") - ord(char) + 1 for char in input_string.lower()]
Enter fullscreen mode Exit fullscreen mode

Finally I use the sum function and list comprehension to compute the correct number.

    return sum(number * pos for number, pos in enumerate(numbers, start=1))
Enter fullscreen mode Exit fullscreen mode

The Perl solution is similar. To compute the correct number, I use the pre-increment operator ++$pos and the map function. The map function is also used to generate the numbers array.

use List::Util 'sum';

sub main ($input_string) {
    if ( $input_string !~ /^[a-zA-Z]*$/ ) {
        die "String must only contain English letters\n";
    }

    my @numbers = map { ord("z") - ord($_) + 1 } split //, lc $input_string;
    my $pos     = 0;
    say sum( map { $_ * ++$pos } @numbers );
}
Enter fullscreen mode Exit fullscreen mode

Examples

$ ./ch-2.py z
1

$ ./ch-2.py a
26

$ ./ch-2.py bbc
147

$ ./ch-2.py racecar
560

$ ./ch-2.py zyx
14
Enter fullscreen mode Exit fullscreen mode

Top comments (0)