Perl Weekly Challenge 131.

My solutions (task 1, and task 2 ) to the The Weekly Challenge - 131.

Task 1: Consecutive Arrays

Submitted by: Mark Anderson
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])

This seems somewhat straightforward. I accumulate consecutive values in an array and I push it into an array of results when there is a jump in the sequence or there are no more values. I sort the input just in case.

# Perl weekly challenge 131
# Task 1:  Consecutive arrays
#
# See https://wlmb.github.io/2021/09/21/PWC131/#task-1-consecutive-arrays
use v5.12;
use warnings;
say "Input: (", join(", ", @ARGV),")\nOutput: ([",
    join("], [",
    (map {join ", ", @$_}
         consecutives(sort {$a<=>$b} @ARGV))), "])";

sub consecutives { # Return array of arrays of consecutive integers
    my @in=@_; # assume they are integers.
    my @out;
    while(@in){
	my $c=shift @in;
	my @seq=($c);
	push @seq, shift @in while(@in && $in[0]==++$c);
	push @out, [@seq];
    }
    return @out;
}

Examples:

./ch-1.pl 1 2 3 6 7 8 9
./ch-1.pl 11 12 14 17 18 19
./ch-1.pl 2 4 6 8
./ch-1.pl 1 2 3 4 5

Results:

Input: (1, 2, 3, 6, 7, 8, 9)
Output: ([1, 2, 3], [6, 7, 8, 9])
Input: (11, 12, 14, 17, 18, 19)
Output: ([11, 12], [14], [17, 18, 19])
Input: (2, 4, 6, 8)
Output: ([2], [4], [6], [8])
Input: (1, 2, 3, 4, 5)
Output: ([1, 2, 3, 4, 5])

Task 2: Find Pairs

Submitted by: Yary
You are given a string of delimiter pairs and a string to
search.

Write a script to return two strings, the first with any
characters matching the “opening character” set, the second
with any matching the “closing character” set.

Example 1:
Input:
    Delimiter pairs: ""[]()
    Search String: "I like (parens) and the Apple ][+" they said.

Output:
    "(["
    ")]"
Example 2:
Input:
    Delimiter pairs: **//<>
    Search String: /* This is a comment (in some languages) */ <could be a tag>

Output:
    /**/<
    /**/>

The examples show that if there are repetitions they ought to appear on the output repeatedly, that when opening and closing delimiters coincide, they are counted twice, and that order of opening and closing and nestedness are to be ignored. This simplifies the task, but maybe it reduces its usefulness. I solve the problem by looking a char at a time and testing if it belongs to the opening or closing delimiter sets.

# Perl weekly challenge 131
# Task 2: Find pairs
#
# See https://wlmb.github.io/2021/09/21/PWC131/#task-2-find-pairs
use v5.12;
use warnings;
my ($delims, $string)=@ARGV;
my @delims=split '', $delims;
die "Unbalanced delims $delims" unless @delims%2==0; # need even number
my (%open_delim, %close_delim);
map {$open_delim{$delims[2*$_]}=1;
     $close_delim{$delims[2*$_+1]}=1} 0..@delims/2-1;
my (@open,  @close);
map {push @open, $_ if $open_delim{$_};
     push @close, $_ if $close_delim{$_};} split '', $string;
say "Input:\n\tDelimiter pairs: $delims\n",
    "\tSearch string: $string\nOutput:\n\t",
     @open, "\n\t", @close; # avoid interpolated spaces

Example 1:

./ch-2.pl '""[]()' '"I like (parens) and the Apple ][+" they said.'

Results:

Input:
	Delimiter pairs: ""[]()
	Search string: "I like (parens) and the Apple ][+" they said.
Output:
	"(["
	")]"

Example 2:

./ch-2.pl '**//<>' '/* This is a comment (in some languages) */ <could be a tag>'

Results:

Input:
	Delimiter pairs: **//<>
	Search string: /* This is a comment (in some languages) */ <could be a tag>
Output:
	/**/<
	/**/>
Written on September 21, 2021