Perl Weekly Challenge 184: Sequence Number and Split Array
These are some answers to the Week 184 of the Perl Weekly Challenge organized by Mohammad S. Anwar.
Spoiler Alert: This weekly challenge deadline is due in a couple of days from now (on Oct. 2, 2022 at 23:59). This blog post offers some solutions to this challenge, please don’t read on if you intend to complete the challenge on your own.
Task 1: Sequence Number
You are given list of strings in the format aa9999 i.e. first 2 characters can be anything ‘a-z’ followed by 4 digits ‘0-9’.
Write a script to replace the first two characters with sequence starting with ‘00’, ‘01’, ‘02’ etc.
Example 1
Input: @list = ( 'ab1234', 'cd5678', 'ef1342')
Output: ('001234', '015678', '021342')
Example 2
Input: @list = ( 'pq1122', 'rs3334')
Output: ('001122', '013334')
Sequence Number in Raku
The program is fairly straight forward. For various reasons, I found that using the subst
method was slightly more efficient (code-wise) than using a regex substitution.
for <ab1234 cd5678 ef1342>, <pq1122 rs3334> -> @test {
my $i = 0;
my @out;
for @test {
push @out, .subst(/^<[a..z]>**2/, $i.fmt("%02d"));
$i++;
}
say "@test[] => @out[]";
}
This program displays the following output:
$ raku ./sequence-number.raku
ab1234 cd5678 ef1342 => 001234 015678 021342
pq1122 rs3334 => 001122 013334
Sequence Number in Perl
This is essentially a port to Perl of the Raku program above:
use strict;
use warnings;
use feature qw/say/;
for my $test ([<ab1234 cd5678 ef1342>], [<pq1122 rs3334>]) {
my $i = 0;
my @out = @$test;
for (@out) {
my $count = sprintf("%02d", $i);
s/^[a-z]{2}/$count/;
$i++;
}
say "@$test => @out";
}
This program displays the following output:
$ perl ./sequence-number.pl
ab1234 cd5678 ef1342 => 001234 015678 021342
pq1122 rs3334 => 001122 013334
Task 2: Split Array
You are given list of strings containing 0-9 and a-z separated by space only.
Write a script to split the data into two arrays, one for integers and one for alphabets only.
Example 1
Input: @list = ( 'a 1 2 b 0', '3 c 4 d')
Output: [[1,2,0], [3,4]] and [['a','b'], ['c','d']]
Example 2
Input: @list = ( '1 2', 'p q r', 's 3', '4 5 t')
Output: [[1,2], [3], [4,5]] and [['p','q','r'], ['s'], ['t']]
Split Array in Raku
Using grep
to keep either letters or numerals:
for ('a 1 2 b 0', '3 c 4 d'), ('1 2', 'p q r', 's 3', '4 5 t') -> @test {
my (@letters, @digits);
for @test -> $item {
append @letters, grep { /<alpha>+/ }, $item.split(/\s+/);
append @digits, grep { /\d+/ }, $item.split(/\s+/);
}
.say for @letters, @digits;
}
This program displays the following output:
$ raku ./split-array.raku
[a b c d]
[1 2 0 3 4]
[p q r s t]
[1 2 3 4 5]
Split Array in Perl
This is a port to Perl of the above Raku program:
use strict;
use warnings;
use feature qw/say/;
for my $test (['a 1 2 b 0', '3 c 4 d'], ['1 2', 'p q r', 's 3', '4 5 t']) {
my (@letters, @digits);
for my $item (@$test) {
push @letters, grep { /[a-zA-Z]+/ } split /\s+/, $item;
push @digits, grep { /\d+/ } split /\s+/, $item;;
}
say "@letters \n@digits";
}
This program displays the following output:
$ perl ./split-array.pl
a b c d
1 2 0 3 4
p q r s t
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 9, 2022. And, please, also spread the word about the Perl Weekly Challenge if you can.
Leave a comment