Perl Weekly Challenge

Tags:

The Perl Weekly Challenge is an amazing project run by Mohammad Anwar that provides coding challenges on a weekly basis; and more importantly a good variety of approaches written up (or shared as video) by developers in Perl and other programming languages.

This week for example the challenges are/were:

TASK #1: Reverse Words

You are given a string $S. Write a script to reverse the order of words in the given string. The string may contain leading/trailing spaces. The string may have more than one space between words in the string. Print the result without leading/trailing spaces and there should be only one space between words.

TASK #2: Edit Distance

You are given two strings $S1 and $S2. Write a script to find out the minimum operations required to convert $S1 into $S2. The operations can be 'insert', 'remove' or 'replace' a character.

Solving the challenge can be a challenge of finding an approach that works, though sometimes they are also simple. When simple I have found it enjoyable and rewarding to use it as a code kata where I might try different approaches or try solving in multiple programming languages.

So this weeks is one of those ones that clicked in my head so here is a small overview of my solution:

Here is the test...

    # t/pw96.t

    use strict;
    use warnings;

    use Test2::V0 -target => 'pw96';

    my $input    = 'The Weekly Challenge';
    my $expected = 'Challenge Weekly The';

    is $CLASS->reverse_words($input),
        $expected,
        'Example one is correct';


    $input    = '    Perl and   Raku are  part of the same family  ';
    $expected = 'family same the of part are Raku and Perl';

    is $CLASS->reverse_words($input),
        $expected,
        'Example two is correct';

    done_testing;

So as I have mentioned in other places, I default to Test2:V0 where possible. It's modern and full featured. It is a solid "Batteries included" testing library. This is a pretty basic set of tests.

Here is the code that followed the tests...

    # lib/pw96.pm

    package pw96;

    use strict;
    use warnings;

    use Moo;

    sub reverse_words {
        my ($self, $phrase) = @_;

        my @words = split ' ', $phrase;
        return join ' ', reverse @words;
    }

    1;

As you can see it's pretty simple; though in fact it's more complex than actually required.

Why?

Because I have another "default setting", I tend to use the Moo module for some object orientation ease. I don't "need" it so technically I am not doing the "simplest thing that works" depending on how you define simple. In the situation of doing this sort task; using a comfortable setup (Test2::V0 and Moo) means consistency which makes it simple over time?

This is more the making things simple to write, rather than writing the simplest thing.

At this stage I should point out that I did TDD this code; so the first thing I wrote was this:

    use Test2:V0 -target => 'pw96';
    done_testing;

The above failed, as I had not created the lib/pw96.pm file. So I created that with a little boiler plate:

    package pw96;
    1;

Which made the test pass. Next I tested for the method I wanted to write add in:

    can_ok($CLASS, 'reverse_words');

After watching that fail, I added this in the module:

    use Moo;
    sub reverse_words{}

All good! After which I added my first practical test (and deleting the can_ok test).

    my $input    = 'The Weekly Challenge';
    my $expected = 'Challenge Weekly The';

    is $CLASS->reverse_words($input),
        $expected,
        'Example one is correct';

After which I wrote the method in a basic way. Once that was working; I refined it to the two line solution. You could take it down a bit more; but where it sits is a nice balance of conciseness and simplicity to read.

So there you have it my solution to this weeks Perl Weekly Challenge.