Logo

dev-resources.site

for different kinds of informations.

PWC 269 Two of Us Distributing Elements

Published at
5/15/2024
Categories
perl
perlweeklychallenge
pwc
Author
boblied
Categories
3 categories in total
perl
open
perlweeklychallenge
open
pwc
open
Author
7 person written this
boblied
open
PWC 269 Two of Us Distributing Elements

You and I have memories, longer than the road that stretches out ahead. Remember when refactoring was a Big Deal? Let's do some of that this week.

Two of Us Lyrics Music

Task 2: Distribute Elements

You are given an array of distinct integers, @ints.

Write a script to distribute the elements as
described below:

1) Put the 1st element of the given array to
a new array @arr1.
2) Put the 2nd element of the given array to
a new array @arr2.

Once you have one element in each arrays,
@arr1 and @arr2, then follow the rule below:

If the last element of the array @arr1 is greater
than the last element of the array @arr2, then
add the first element of the given array to @arr1,
otherwise to the array @arr2.

When done distribution, return the concatenated
arrays, @arr1 and @arr2.
Enter fullscreen mode Exit fullscreen mode

Example 1

  • Input: @ints = (2, 1, 3, 4, 5)
  • Output: (2, 3, 4, 5, 1)

    • 1st operation: Add 2 to @arr1 = (2)
    • 2nd operation: Add 1 to @arr2 = (1)
    • 3rd operation: Now the last element of @arr1 is greater than the last element of @arr2, so add 3 to @arr1 = (2, 3).
    • 4th operation: Again the last element of @arr1 is greater than the last element of @arr2, add 4 to @arr1 = (2, 3, 4)
    • 5th operation: Finally, the last element of @arr1 is again greater than the last element of @arr2, add 5 to @arr1 = (2, 3, 4, 5)
    • Now we have two arrays: @arr1 = (2, 3, 4, 5) and @arr2 = (1)
    • Concatenate the two arrays and return the final array: (2, 3, 4, 5, 1).

Phase 1, in which Doris gets her oats

That's a very prescriptive specification and example. We could hardly do anything else.

sub distElem(@ints) 
{
    my @arr1 = shift @ints; 
    my @arr2 = shift @ints; 
    while ( defined(my $n = shift @ints) )
    {
        if ( $arr1[-1] > $arr2[-1] ) {
            push @arr1, $n;
        } else {
            push @arr2, $n;
        }
    }
    return [ @arr1, @arr2 ];
}
Enter fullscreen mode Exit fullscreen mode

Perl notes:

  • We're using up the @ints array by shifting off one element at a time. Numbers could be zero, and we don't want that interpreted as false, so the accurate check is to look for the undef when the array becomes empty.
  • Perl can index from the end by using negative offsets. We don't have to do any bookkeeping about the lengths of the arrays.

Sunday driving, not arriving

It irks me to have the two variables named arr1 and arr2. What is this, BASIC? It's a list of two arrays, so let's do that refactoring.

sub distElem(@ints) 
{
    my @arr = ( [shift @ints], [shift @ints] );
    while ( defined(my $n = shift @ints) )
    {
        if ( $arr[0][-1] > $arr2[1][-1] ) {
            push @{$arr[0]}, $n;
        } else {
            push @{$arr[1]}, $n;
        }
    }
    return [ $arr[0]->@*, $arr[1]->@* ];
}
Enter fullscreen mode Exit fullscreen mode

Perl notes:

  • We now have an array of two references to arrays, so we see array de-referencing syntax. The first argument to push needs to be an array, so the @{...} turns the reference into an array. In the return statement, I use newer-style postfix de-referencing.

Burning matches, lifting latches

Now I'm annoyed by that if statement. We only have to choose between 0 and 1, and we have a condition that will be either true or false. Zero, one; false, true. Po-tay-to, po-tah-to. Let's use that condition to make an index.

sub distElem(@ints) 
{
    my @arr = ( [shift @ints], [shift @ints] );
    while ( defined(my $n = shift @ints) )
    {
        my $which = ( $arr[0][-1] <= $arr[1][-1] );
        push @{$arr[$which]}, $n;
    }
    return [ $arr[0]->@*, $arr[1->@*} ];
}
Enter fullscreen mode Exit fullscreen mode

Perl notes:

  • True and false values will be interpreted as 1 and zero, respectively, when used in an arithmetic context.
  • I changed the test from > to <= so that the array order is the same.

Chasing paper, getting nowhere

Introducing the $which variable seems arbitrary. Let's put that in-line.

sub distElem(@ints) 
{
    my @arr = ( [shift @ints], [shift @ints] );
    while ( defined(my $n = shift @ints) )
    {
        push @{$arr[ $arr[0][-1] <= $arr[1][-1 ]}, $n;
    }
    return [ $arr[0]->@*, $arr[1->@*} ];
}
Enter fullscreen mode Exit fullscreen mode

Wearing raincoats, standing solo

Why am I chewing up the @ints array with shifts? Let's just iterate over it.

sub distElem(@ints) 
{
    my @arr = ( [shift @ints], [shift @ints] );
    push @{$arr[ $arr[0][-1] <= $arr[1][-1 ]}, $_ for @ints;
    return [ $arr[0]->@*, $arr[1->@*} ];
}
Enter fullscreen mode Exit fullscreen mode

We're on our way home, we're going home

One last thing: can we make it do reasonable things when the @ints array has 0 or 1 elements? Currently, that inital shift to initialize @arr would put an undef value into the lists. Let's account for the possibility.

sub distElem(@ints)
{
    my @arr = ( [ (shift @ints) // () ], [ (shift @ints) // () ] );

    push @{$arr[ ( $arr[0][-1] <= $arr[1][-1] ) ]}, $_ for @ints;

    return [ $arr[0]->@*, $arr[1]->@* ];
}
Enter fullscreen mode Exit fullscreen mode

Perl notes:

  • shift on an empty array will yield undef, but we want an empty list in that case.
  • The // operator is really useful for checking defined-ness. In the old days, code was littered with if (defined(...)) tests.

The long and winding road (oops, wrong song)

That was the process I used to get from 11 lines to 3. Of course, there were unit tests executed at every step. The final code, including tests is in GitHub

perlweeklychallenge Article's
30 articles in total
Favicon
Maximally Indexed Indices (PWC 298)
Favicon
PWC 296 String Compression
Favicon
PWC 293 Similar Dominos Done Badly
Favicon
Jump, but Don't Break the Game (PWC 295)
Favicon
Ups and Downs, Beginnings and Ends (PWC 297)
Favicon
Consecutive Sequences of Permutations, Anyone? (PWC 294)
Favicon
PWC 293 Similar Dominos Done Badly
Favicon
Domino Frequencies and the Vectorized Boomerang (PWC 293)
Favicon
PWC 287 Strength in Numbers
Favicon
PWC 281 Knight's Move
Favicon
PWC 274 Waiting at the Bus Stop
Favicon
PWC 269 Two of Us Distributing Elements
Favicon
PWC 267 Positively Perl Street
Favicon
PWC 268 Games Numbers Play
Favicon
PWC 263.1 Don't Sort It, Be Happy
Favicon
PWC 262 Grep it once, grep it twice
Favicon
PWC 258 How do I sum thee? Let me count the ones.
Favicon
PWC 259 Something I think's worthwhile if a parser makes you smile
Favicon
PWC 254, Task 2: I, Too, Wish to Make the "Vowel Movement" Joke
Favicon
PWC 254 Task 1, Three Power
Favicon
PWC 252 Special Numbers
Favicon
PWC 246 Random use of algebra
Favicon
Let me count the ways (PWC 244 Count Smaller)
Favicon
PWC 241 Triplets, sorting, and a profiling digression
Favicon
PWC 242 Flip the Script
Favicon
PWC 243 Sweeping the floor
Favicon
PWC 238 Running and Persistence
Favicon
PWC 239 Adagio for frayed knots
Favicon
PWC 235 Steppin' in a Slide Zone
Favicon
PWC 236 Task 1 A Change Would Do You Good

Featured ones: