Perl Weekly Challenge 131: Consecutive Arrays

These are some answers to task 1 of the Week 131 of the Perl Weekly Challenge organized by Mohammad S. Anwar.

Spoiler Alert: This weekly challenge deadline is due in a few days from now (on September 26, 2021 at 24:00). This blog post offers some solutions to this challenge, please don’t read on if you intend to complete the challenge on your own.

You are given a sorted list of unique positive integers.

Write a script to return list of arrays where the arrays are consecutive integers.

Example 1:

Input:  (1, 2, 3, 6, 7, 8, 9)
Output: ([1, 2, 3], [6, 7, 8, 9])

Example 2:

Input:  (11, 12, 14, 17, 18, 19)
Output: ([11, 12], [14], [17, 18, 19])

Example 3:

Input:  (2, 4, 6, 8)
Output: ([2], [4], [6], [8])

Example 4:

Input:  (1, 2, 3, 4, 5)
Output: ([1, 2, 3, 4, 5])

Consecutive Arrays in Raku

We implement the four example arrays provided as an array of arrays (AoA) for our tests. For each input test array, we simply loop over the values. If a value is the integer next to the previous one ($prev), we add it to a @tmp-res temporary array. If not (i.e. there is a gap), we push @tmp-res to the @result array, and reset @tmp-res to an array containing only the current value. At the end, we push the last @tmp-res to the result.

use v6;

my @tests = [1, 2, 3, 6, 7, 8, 9],
            [11, 12, 14, 17, 18, 19],
            [2, 4, 6, 8],
            [1, 2, 3, 4, 5];
for @tests -> @input {
    my $prev = shift @input;
    my @result;
    my @tmp-res = $prev;
    for @input -> $i {
        if $i == $prev + 1 {
            push @tmp-res, $i;
        } else {
            push @result, [@tmp-res];
            @tmp-res = $i;
        }
        $prev = $i;
    }
    push @result, @tmp-res;
    say @result;
}

This script displays the following output:

raku ./main.raku
[[1 2 3] [6 7 8 9]]
[[11 12] [14] [17 18 19]]
[[2] [4] [6] [8]]
[[1 2 3 4 5]]

Consecutive Arrays in Perl

The Perl solution is essentially a port to Perl of the Raku script above. The only significant difference is that it is slightly less easy to print out the contents of an array of arrays, as we need to dereference the sub-array references.

#!/usr/bin/perl
use strict;
use warnings;
use feature qw/say/;

my @tests = ( [1, 2, 3, 6, 7, 8, 9],
              [11, 12, 14, 17, 18, 19],
              [2, 4, 6, 8],
              [1, 2, 3, 4, 5]
            );
for my $test (@tests) {
    my @input = @$test;
    my $prev = shift @input;
    my @result;
    my @tmp_res = ($prev);
    for my $i (@input) {
        if ($i == $prev + 1) {
            push @tmp_res, $i;
        } else {
            push @result, [@tmp_res];
            @tmp_res = ($i);
        }
        $prev = $i;
        # say "tmp ",  @tmp-res;
    }
    push @result, [@tmp_res];
    say "( ", (map "[@$_] ", @result), ")";
}

This script displays the following output:

$ perl  ./consec_arrays.pl
( [1 2 3] [6 7 8 9] )
( [11 12] [14] [17 18 19] )
( [2] [4] [6] [8] )
( [1 2 3 4 5] )

Wrapping up

The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on October 3, 2021. And, please, also spread the word about the Perl Weekly Challenge if you can.

Leave a comment

About laurent_r

user-pic I am the author of the "Think Perl 6" book (O'Reilly, 2017) and I blog about the Perl 5 and Raku programming languages.