Weekly Challenge 322
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.
Task 1: String Format
Task
You are given a string and a positive integer.
Write a script to format the string, removing any dashes, in groups of size given by the integer. The first group can be smaller than the integer but should have at least one character. Groups should be separated by dashes.
My solution
There is probably a way to do this using regular expression. However that would take away the readability of the solution.
For this task, I start by removing all the existing dashes in the input_string
(and yes, with regular expressions for the Perl solution). I then calculate the start
variable by taking the modulus of the length of input_string
from size
.
If this is not zero, we need to capture the first part of the string (the first start
letters), and put this in the parts
list (array in Perl).
I then have a loop from start
to the length of input_string
, increasing by size
each time. For each iteration, I add to the parts
list with the characters from pos
to pos + size -1
.
Finally, I join the parts
list with hyphens to produce the final solution.
def string_format(input_string: str, size: int) -> str:
input_string = input_string.replace("-", "")
start = len(input_string) % size
parts = []
if start:
parts.append(input_string[0:start])
for pos in range(start, len(input_string), size):
parts.append(input_string[pos:pos+size])
return '-'.join(parts)
The Perl solution follows the same logic, but uses the substr
function to retrieve parts of the string.
sub main ( $input_string, $size ) {
$input_string =~ s/-//g;
my $start = length($input_string) % $size;
my @parts = ();
if ($start) {
push @parts, substr( $input_string, 0, $start );
}
for ( my $pos=$start; $pos < length($input_string); $pos+=$size ) {
push @parts, substr( $input_string, $pos, $size );
}
say join( '-', @parts );
}
Examples
$ ./ch-1.py ABC-D-E-F 3
ABC-DEF
$ ./ch-1.py A-BC-D-E 2
A-BC-DE
$ ./ch-1.py A-B-CD-E 4
A-BCDE
Task 2: Rank Array
Task
You are given an array of integers.
Write a script to return an array of the ranks of each element: the lowest value has rank 1, next lowest rank 2, etc. If two elements are the same then they share the same rank.
My solution
This is relatively straight forward, and two lines in Python. I create a list called sorted_list
which has the unique integers sorted numerically. By converting the list to a set, we remove any duplicate integers.
I then use list comprehension to find the index of each integer in ints
in sorted_list
. Each value is incremented by 1, as the solution is one-based.
def rank_array(ints: list) -> list:
sorted_list = sorted(set(ints))
return [sorted_list.index(i)+1 for i in ints]
The Perl solution is a little more involved, as it does not have list comprehension. Well that's not entirely true, there is the map
function.
For the Perl solution, I start by creating sorted_array
which has the unique integers sorted numerically. I then have a foreach
loop which uses the first_index function to find the position of that integer in the sorted_array
array. Like with the Python solution, we increment the value by one.
sub main (@ints) {
my @sorted_array = sort { $a <=> $b } uniq(@ints);
my @solution = ();
foreach my $int (@ints) {
my $idx = first_index { $_ == $int } @sorted_array;
push @solution, $idx + 1;
}
say '(', join( ', ', @solution ), ')';
}
Examples
$ ./ch-2.py 55 22 44 33
[4, 1, 3, 2]
$ ./ch-2.py 10 10 10
[1, 1, 1]
$ ./ch-2.py 5 1 1 4 3
[4, 1, 1, 3, 2]
Top comments (0)