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.
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(" ")
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
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
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 . '"';
}
}
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 "
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
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;
}
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
Top comments (0)