DEV Community

Simon Green
Simon Green

Posted on

Weekly Challenge: Distant spaces

Weekly Challenge 372

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: Rearrange Spaces

Task

You are given a string text of words that are placed among number of spaces.

Write a script to rearrange the spaces so that there is an equal number of spaces between every pair of adjacent words and that number is maximized. If you can’t distribute, place the extra spaces at the end. Finally return the string.

My solution

This is a little more straight forward than last weeks challenge one task. For this task, I take start by separating the words on whitespace, and count the number of spaces. This is stored in the words list (array in Perl) and spaces variable.

def rearrange_space(input_string: str) -> str:
    words = input_string.split()
    spaces = input_string.count(" ")
Enter fullscreen mode Exit fullscreen mode

To avoid a division by zero error, I handle the case where there is a single word. For this I return the word followed by the required number of spaces. In Python, a string multiple by an integer will repeat the string the specified number of times.

    if len(words) == 1:
        return words[0] + " " * spaces
Enter fullscreen mode Exit fullscreen mode

If there is more than one word, I calculate the spaces_between_words and spaces_at_end using the divmod function. I return the string with the spaces in the appropriate places.

    spaces_between_words, spaces_at_end = divmod(spaces, len(words)-1)
    return (" " * spaces_between_words).join(words) + " " * spaces_at_end
Enter fullscreen mode Exit fullscreen mode

The Perl solution uses the same logic. As it does not have a divmod function, I calculate the two values separately. The x operator in Perl is used for repetition. The expression $#words returns one less than the length of the words array.

sub main ($input_string) {
    my @words  = grep { $_ ne "" } split /\s+/, $input_string;
    my $spaces = ( $input_string =~ tr/ / / );

    if ( $#words == 0 ) {
        say '"' . $words[0] . " " x $spaces . '"';
    }
    else {
        my $spaces_between_words = int( $spaces / $#words );
        my $spaces_at_end        = $spaces % $#words;
        say '"'
          . join( " " x $spaces_between_words, @words )
          . " " x $spaces_at_end . '"';
    }
}
Enter fullscreen mode Exit fullscreen mode

Examples

$ ./ch-1.py "  challenge  "
"challenge    "

$ ./ch-1.py "coding  is  fun"
"coding  is  fun"

$ ./ch-1.py "a b c  d"
"a b c d "

$ ./ch-1.py "  team      pwc  "
"team          pwc"

$ ./ch-1.py "   the  weekly  challenge  "
"the    weekly    challenge "
Enter fullscreen mode Exit fullscreen mode

Task 2: Largest Substring

Task

You are given a string.

Write a script to return the length of the largest substring between two equal characters excluding the two characters. Return -1 if there is no such substring.

My solution

For this task, I start by creating a dict (hash in Perl) called freq with the frequency of each letter. In Python, this is achieved with the Counters function from the collections module.

I then iterate through the dict. If the letter occurs more than once, I calculate the difference between position of the first and last occurrence, minus one. Both Python and Perl have the index and rindex methods to do this. I update the largest value if this is greater than previously found values.

from collections import Counter

def largest_substring(input_string: str) -> int:
    freq = Counter(input_string)
    largest = -1

    for letter, count in freq.items():
        if count > 1:
            substr = input_string.rindex(letter) - input_string.index(letter) - 1
            if substr > largest:
                largest = substr

    return largest
Enter fullscreen mode Exit fullscreen mode

The Perl solution follows the same logic.

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

    while ( my ( $letter, $count ) = each %freq ) {
        if ( $count > 1 ) {
            my $substr = rindex( $input_string, $letter ) -
              index( $input_string, $letter ) - 1;
            $largest = $substr if ( $substr > $largest );
        }
    }

    say $largest;
}
Enter fullscreen mode Exit fullscreen mode

Examples

$ ./ch-2.py aaaaa
3

$ ./ch-2.py abcdeba
5

$ ./ch-2.py abbc
0

$ ./ch-2.py abcaacbc
4

$ ./ch-2.py laptop
2

$ ./ch-2.py abc
-1
Enter fullscreen mode Exit fullscreen mode

Top comments (0)