loading...

Weekly Challenge #087 Task #1 :: (Perl, Raku)

jeongoon profile image Myoungjin Jeon Updated on ・3 min read

TASK #1 › Longest Consecutive Sequence

Submitted by: Mohammad S Anwar

You are given an unsorted array of integers @N.

Write a script to find the longest consecutive sequence. Print 0 if none sequence found.

Example 1:

Input: @N = (100, 4, 50, 3, 2)
Output: (2, 3, 4)

Example 2:

Input: @N = (20, 30, 10, 40, 50)
Output: 0

Example 3:

Input: @N = (20, 19, 9, 11, 10)
Output: (9, 10, 11)
Enter fullscreen mode Exit fullscreen mode

Perl Solution

Imperative Approach

I've done the same task with common lisp and golang, then I guess that I naturally follow the same logic I used in both language.

  1. sort the number
  2. compare between consecutive member in the list
  3. concatenate the list if they are right next to each other
  4. if not, start a new sequence

and I need to add handy dummy member at the tail of the list

here is the code.

use strict; use warnings;
use v5.26;

# note: no sanity check !!
my @sorted = sort { $a <=> $b } @ARGV;
push @sorted, $sorted[-1]+2; # dummy

my @longest_seq_list = ();
my $longest_size = 0;

my $prev = shift @sorted;
my @curr_seq = ($prev);

for my $curr (@sorted) {
    if ( $curr - $prev == 1 ) {
        push @curr_seq, ($curr);        # concat. current seq
    } elsif ( $curr == $prev ) {        # skip
    } else {                            # update longest
        my $curr_size = scalar @curr_seq;
        if ( $curr_size > $longest_size ) {
            $longest_size = $curr_size;
            @longest_seq_list = ( [ @curr_seq ] );
        } elsif ( $curr_size == $longest_size ) {
            push @longest_seq_list, [ @curr_seq ];
        }
        @curr_seq = ($curr);
    }
    $prev = $curr;
}

if ( $longest_size > 0 ) {
    say "longest size: ".$longest_size;
    say "total ".(scalar @longest_seq_list)." sequencies found.";
    for my $seq (@longest_seq_list) {
        say "[", join(", ", @$seq), "]";
    }
}
Enter fullscreen mode Exit fullscreen mode

It is simple challenge, so I tried learn more about raku today.

Raku Solution

Sorting

Easy!, and we don't need to add 'sort( $^a <=> $^b )' because @n are all already IntStr instance.

unit sub MAIN (*@n where { @n ~~ Int, @n.elems > 0 } );
@n.sort.say
Enter fullscreen mode Exit fullscreen mode

Produce

as we go through the list, we can produce the trace of our data.
the simple example of produce is that maximum value at each step.

> my @n = 3, 2, 4, 5, 9;
[3 2 4 5 9]
> @n.produce( -> \a, \b { max( a, b) } )
(3 3 4 5 9)
Enter fullscreen mode Exit fullscreen mode

but I need some more information to keep at every step and decided to keep a list of numbers as we go.

> @n = -3, 1, 3, 2, -2, 4, 6, 7, -1, 4
> @n.sort.map({[$_]})
([-3] [-2] [-1] [1] [2] [3] [4] [4] [6] [7])
Enter fullscreen mode Exit fullscreen mode

and if a and b is consecutive write down the linked numbers or start over new one.

...
(@n.sort.map({[$_]})).
produce( ->  \a, \b {
                 b.first - a.tail == 1
                 ?? a.append(b.first).clone
                 !! b.clone
           } ).say
...
Enter fullscreen mode Exit fullscreen mode

and result looks like:

([-4] [-4 -3] [-4 -3 -2] [-4 -3 -2 -1] [1] [1 2] [1 2 3] [1 2 3 4] [6] [6 7])
Enter fullscreen mode Exit fullscreen mode

Now classify the number by length and grep the element has maximum size and say!

...
classify( {.elems} ).
max.
value.
map( *.say );
...
Enter fullscreen mode Exit fullscreen mode

Final Code

unit sub MAIN (*@n where { @n ~~ Int, @n.elems > 0 } );
(@n.sort.map({[$_]})).
produce( ->  \a, \b {
                 b.first - a.tail == 1
                 ?? a.append(b.first).clone
                 !! b.clone
           } ).
classify( {.elems} ).
max.
value.
map( *.say );
Enter fullscreen mode Exit fullscreen mode

Happy Coding!!
I spent too much time on common-lisp and golang.
I'm so sorry to say that I'll skip blog about task #2.

May Perl and Raku be with you!!
🐪PWC🦋

Discussion

pic
Editor guide