Advent Calendar - December 24, 2020

Thursday, Dec 24, 2020| Tags: Perl, Raku

Advent Calendar 2020


TABLE OF CONTENTS


1. Headlines

2. Leader Elements

3. YouTube Video

4. Perl Solution

5. Raku Solution


Headlines


Finally we reached the end of the Advent Calendar 2020. I wasn’t prepared for Advent Calendar this year initially as I knew I wouldn’t be able to do it. However, on the day one, I pushed myself and decided to give it a try. Now, today I am doing the last day blog for the same. Although, I didn’t do it regularly, still I am happy with my effort.

I would like to thank the following Team PWC members for the contribution to the Advent Calendar 2020.

Jaldhar H. Vyas, Ryan Thompson, E. Choroba, Andrew Shitov, Dave Jacoby, Luca Ferarri, Javier Luque, Roger Bell_West, Arne Sommer, Walt Mankowski, Adam Russell, Cheok-Yin Fung, Bartosz Jarzyna, Myoungjin Jeon, Laurent Rosenfeld, Yet Ebreo, Scimon Proctor, Kevin Colyer, Duncan C. White, Yozen Hernandez, Saif Ahmed, Noud Aldenhoven and James Smith.

Today I am talking about my solutions to the task Leader Elements of “The Weekly Challenge - 078”.


Leader Elements

Submitted by Mohammad S Anwar


You are given an array @A containing distinct integers.

Write a script to find all leader elements in the array @A.

An element is leader if it is greater than all the elements to its right side.

Example 1:

Input: @A = (9, 10, 7, 5, 6, 1)
Output: (10, 7, 6, 1)

Example 2:

Input: @A = (3, 4, 5)
Output: (5)

YouTube Video


Do you prefer watching action than reading text?

If yes then please take a look live action video dealing with the Leader Elements task.




Perl Solution


The Leader Elements task is best suited for beginners. I never done array slicing in my current job. So when I decided to do for this task, I had to lookup documentation. I have used it few times in the recent week, so it was fresh. Once that is sorted, rest is just walk in the park as you see in the code below.

sub leader_elements {
    my ($list) = @_;

    my @leaders = ();
    my $i       = 0;
    my @array   = @$list;
    foreach my $n (@array) {
        if ($i == $#array) {
            push @leaders, $n;
        }
        else {
            push @leaders, $n
                if ($n > max(@array[$i+1 .. $#array]));
        }
        $i++;
    }

    return @leaders;
}

For this task, I created sub get_list() to help with user input validation and converting the input string into array ref.


sub get_list {
    my ($l) = @_;

    die "ERROR: Missing list.\n"      unless defined $l;
    die "ERROR: Invalid list [$l].\n" unless ($l =~ /^[\-?\d\,?\s?]+$/);

    $l =~ s/\s//g;
    return [ split /\,/, $l ];
}

Time for one-liner solution to the task.


use strict;
use warnings;
use List::Util qw(max);

printf("%s\n", join(", ", leader_elements(get_list($ARGV[0]))));

Standard unit test using the examples in the given tasks. Sorry.


use strict;
use warnings;
use Test::More;
use Test::Deep;
use List::Util qw(max);

is_deeply([leader_elements([9, 10, 7, 5, 6, 1])],
          [10, 7, 6, 1],
          "testing example 1");

is_deeply([leader_elements([3, 4, 5])],
          [5],
          "testing example 2");

done_testing;

Raku Solution


For Raku, I didn’t create any helper method. Everything needed for the task brought together in the following sub leader-elements().

sub leader-elements(Str $list) {

    die "ERROR: Invalid list [$list].\n" unless $list ~~ /^[\-?\d\,?\s?]+$/;

    my @array = $list.split(',').map: { .Int };
    my $index = 0;
    my @leader-elements = Empty;
    for @array -> $n {
        if $index == @array.elems-1 {
            @leader-elements.push: $n;
        }
        else {
            @leader-elements.push: $n
                if $n > @array[$index+1 .. @array.elems-1].max;
        }
        $index++;
    }

    return |@leader-elements;
}

My favourite line is below, which coverts the given string into an array of integers.


my @array = $list.split(',').map: { .Int };

and one small magic is array slicing and max combined.


@array[$index+1 .. @array.elems-1].max;

Same goes to Raku as well. Here I present my one-liner solution in Raku.


use v6.d;

sub MAIN(Str :$L = "9, 10, 7, 5, 6, 1") {
    leader-elements($L).join(", ").say;
}

Raku follows the same path as Perl.


use Test;

is-deeply leader-elements("9, 10, 7, 5, 6, 1"),
          (10, 7, 6, 1),
          "testing example 1";

is-deeply leader-elements("3, 4, 5"),
          (5),
          "testing example 2";

done-testing;

If you have any suggestion then please do share with us perlweeklychallenge@yahoo.com.

Advent Calendar 2020

SO WHAT DO YOU THINK ?

If you have any suggestions or ideas then please do share with us.

Contact with me