VOOZH about

URL: https://dev.to/simongreennet/weekly-challenge-joining-and-splitting-lists-18gh

⇱ Weekly Challenge: Joining and splitting lists - DEV Community


Weekly Challenge 373

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: Equal List

Task

You are given two arrays of strings.

Write a script to return true if the two given array represent the same strings otherwise false.

My solution

For input from the command line, I take a string with items concatenated by commas to generate the two lists. This seems to the easiest way to handle this, allowing for empty items as per the fourth example.

def main():
 result = equal_list(sys.argv[1].split(","), sys.argv[2].split(","))
 print("true" if result else "false")

This function is a one liner. I join the items in each list and then compare them to see if they are the same.

def equal_list(arr1: list[str], arr2: list[str]) -> bool:
 return ''.join(arr1) == ''.join(arr2)

The Perl solution has the same functionality.

sub main ( $str1, $str2 ) {
 my @arr1 = split /,/, $str1;
 my @arr2 = split /,/, $str2;

 say join( "", @arr1 ) eq join( "", @arr2 ) ? "true" : "false";
}

Examples

$ ./ch-1.py "a,bc" "ab,c"
false

$ ./ch-1.py "a,bc" "ab,c"
true

$ ./ch-1.py "a,b,c" "a,bc"
true

$ ./ch-1.py "a,bc" "a,c,b"
false

$ ./ch-1.py "ab,c," ",a,bc"
true

$ ./ch-1.py "p,e,r,l" "perl"
true

Task 2: List Division

Task

You are given a list and a non-negative integer.

Write a script to divide the given list into given non-negative integer equal parts. Return -1 if the integer is more than the size of the list.

My solution

For this task, I use the divmod function to calculate the number of items from the list each part needs, and the number of parts that require an extra item. These are stored as the variables item_length and extra_first.

I also have a variable called pos to store the position of the first letter. I have a loop i that runs n times. If i is less than extra_first, I take item_length + 1 items, otherwise item_length times, adding to pos as I go.

def list_division(input_list: list[int], n: int) -> list[list[int]] | None:
 result = []
 pos = 0

 if len(input_list) < n:
 return None

 item_length, extra_first = divmod(len(input_list), n)

 for i in range(n):
 this_length = item_length + 1 if i < extra_first else item_length
 result.append(input_list[pos:pos+this_length])
 pos += this_length

 return result

The Perl solution is similar. It doesn't have the pos variable, as it uses the splice function to remove the necessary number of items from the array. This function returns the items removed.

sub main (@list) {
 # The last value is the 'n' value
 my $n = pop(@list);
 my $length = scalar(@list);

 my @result = ();

 if ( $length < $n ) {
 say -1;
 return;
 }

 my $item_length = int( $length / $n );
 my $extra_first = $length % $n;

 foreach my $i ( 1 .. $n ) {
 my $this_length = $i <= $extra_first ? $item_length + 1 : $item_length;
 push @result, "(" . join( ",", splice( @list, 0, $this_length ) ) . ")";
 }

 say "(" . join( ", ", @result ) . ")";
}

Examples

$ ./ch-2.py 1 2 3 4 5 2
((1,2,3), (4,5))

$ ./ch-2.py 1 2 3 4 5 6 3
((1,2), (3,4), (5,6))

$ ./ch-2.py 1 2 3 2
((1,2), (3))

$ ./ch-2.py 1 2 3 4 5 6 7 8 9 10 5
((1,2), (3,4), (5,6), (7,8), (9,10))

$ ./ch-2.py 1 2 3 4
-1

$ ./ch-2.py 72 57 89 55 36 84 10 95 99 35 7 
((72,57), (89,55), (36,84), (10), (95), (99), (35))