Perl Weekly Challenge 34: Array and Hash Slices and Dispatch Tables

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

Spoiler Alert: This weekly challenge deadline is due in a few days (November 17, 2019). This blog post offers some solutions to this challenge, please don’t read on if you intend to complete the challenge on your own.

This week, both tasks were contributed by Dave Cross.

Task # 1: Array and Hash Slices

Write a program that demonstrates using hash slices and/or array slices.

Slices are a way to access several values of an array or of a hash in one statement, by using multiple subscripts or keys.

Array and Hash Slices in Perl 5

If you have an @array containing for example some successive integers, you can obtain several values from it with the following syntax: @array[3, 7, 2] or even @array[2..7].

If you try to do the same with a %hash and use %hash{'a', 'c'} you’ll get key/value pairs, which may or may not be what you want. If you want only the values, you need to change the sigil like so: @hash{'a', 'c'}. Array and hash slices may also be used as l-values, i.e. on the left-hand side of an assignment, to populate a new array or a new hash.

This short program illustrates all this:

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

my @array = (0..10);
my $count = 0;
my %hash  = map {$_ => ++$count} 'a'..'j';

say "Array slice :  @array[3..7]";
say "Hash slice 1: ", join ' ', %hash{'b', 'd', 'c'};
say "Hash slice 2: ", join ' ', %hash{'b'..'d'};
say "Hash slice 3: ", join ' ', @hash{'b'..'d'};
say "Hash slice 4: ", join ' ', @hash{qw/c b c d/};

# Array slice a l-value
my @new_array = (1, 2);
@new_array[2, 3] = @array[6, 7];
say "New array: ";
say Dumper \@new_array;    

# Hash slice as l-value:
my @keys = qw/c d e/;
my %new_hash = %hash{@keys}; # Perl 5.20 and above
say "New hash: ";
say Dumper \%new_hash;
my %new_hash2;
@new_hash2{@keys} = @hash{@keys};
say "New hash2: ";
say Dumper \%new_hash2;

This displays the following output:

$ perl hash_slices.pl
Array slice :  3 4 5 6 7
Hash slice 1: b 2 d 4 c 3
Hash slice 2: b 2 c 3 d 4
Hash slice 3: 2 3 4
Hash slice 4: 3 2 3 4
New array:
$VAR1 = [
          1,
          2,
          6,
          7
        ];

New hash:
$VAR1 = {
          'd' => 4,
          'c' => 3,
          'e' => 5
        };

New hash2:
$VAR1 = {
          'e' => 5,
          'c' => 3,
          'd' => 4
        };

Array and Hash Slices in Raku (formerly known as Perl 6)

Like in Perl 5, if you have an @array containing for example some successive integers, you can obtain several values from it with the following syntax: @array[3, 7, 2] or even @array[2..7].

And you can do the same with a hash to obtain a bunch of values. Array and hash slices may also be used as l-values, i.e. on the left-hand side of an assignment, to populate a new array or a new hash.

use v6;

my @array = 0..10;
my $count = 0;
my %hash  = map {$_ => ++$count}, 'a'..'j';

say "Array slice :  @array[3..7]";
say "Hash slice 1: ", join ' ', %hash{'b', 'd', 'c'};
say "Hash slice 2: ", join ' ', %hash{'b'..'d'};
say "Hash slice 3: ", join ' ', %hash<b c d>;

# Array slice a l-value
my @new-array = (1, 2);
@new-array[2, 3] = @array[6, 7];
say "New array: ", @new-array;
# Hash slice as l-value:
my @keys = qw/c d e/;
my %new-hash;
%new-hash{@keys} = %hash{@keys};
say "New hash: ", %new-hash;

This program produces the following output:

$ perl6 hash_slices.p6
Array slice :  3 4 5 6 7
Hash slice 1: 2 4 3
Hash slice 2: 2 3 4
Hash slice 3: 2 3 4
New array: [1 2 6 7]
New hash: {c => 3, d => 4, e => 5}

Task # 2: Dispatch Tables

Write a program that demonstrates a dispatch table.

A dispatch table is a table or more commonly hash of subroutine references.

For this task, we won’t simply demonstrate the syntax, but will try to do something (moderately) useful with it.

Suppose we have a text file and want to feed each word from the file into 26 files (one per letter of the alphabet) depending on the first letter of the word. This could be done with a monstrous if ... elsif ... else (or, in Raku, given ... when) construct, or we could use a dispatch table, in this case a hash containing for each letter a code reference printing the word into the proper file. As we will see, this produces much shorter and simpler code. We will even use a dynamic dispatch table, i.e. only create the hash entries (and files) that are needed with the input file.

Dispatch Tables in Perl 5

We first write a function_builder subroutine that acts as a function factory. It receives a letter as a parameter, creates a file name for that letter, opens the corresponding file in write mode, and it returns an anonymous subroutine (actually a closure) that writes its argument to the file handle. This anonymous subroutine will then be stored into the dispatch table.

In the main loop, the program reads the lines of the input file, fold them to lower case, splits the lines into words, and finds the first character of each such word. To avoid problems with special characters, we only keep words starting with a letter. If the dispatch table has no entry yet for this letter, the program calls function_builder subroutine to open the proper file and stores the code reference returned by that subroutine in the dispatch table. Finally, the program calls the code reference stored in the dispatch table for word’s first letter.

Note that Perl automatically closes files upon exiting.

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

my %dispatch;

sub function_builder {
    my $letter = shift;
    my $file_name = "${letter}_letter.txt";
    open my $FH, ">", $file_name or die "Could not open $file_name $!";
    return sub { say $FH shift }
}

while (<>) {
    chomp;
    for my $word (split / /, lc $_) {
        my $letter = substr $word, 0, 1;
        next if $letter !~ /^[a-z]/; 
        $dispatch{$letter} = function_builder($letter) unless defined $dispatch{$letter};
        $dispatch{$letter}->($word);
    }
}

Running the program and passing it the hash_slices.pl file (the script of task # 1 of this week) produced the following files in the default directory:

-rw-r--r--  1 Laurent Aucun      25 11 nov.  17:48  m_letter.txt
-rw-r--r--  1 Laurent Aucun      20 11 nov.  17:48  j_letter.txt
-rw-r--r--  1 Laurent Aucun      42 11 nov.  17:48  d_letter.txt
-rw-r--r--  1 Laurent Aucun       2 11 nov.  17:48  c_letter.txt
-rw-r--r--  1 Laurent Aucun      28 11 nov.  17:48  a_letter.txt
-rw-r--r--  1 Laurent Aucun      16 11 nov.  17:48  u_letter.txt
-rw-r--r--  1 Laurent Aucun       5 11 nov.  17:48  p_letter.txt
-rw-r--r--  1 Laurent Aucun       4 11 nov.  17:48  e_letter.txt
-rw-r--r--  1 Laurent Aucun      94 11 nov.  17:48  s_letter.txt
-rw-r--r--  1 Laurent Aucun      17 11 nov.  17:48  l_letter.txt
-rw-r--r--  1 Laurent Aucun      18 11 nov.  17:48  h_letter.txt
-rw-r--r--  1 Laurent Aucun      10 11 nov.  17:48  w_letter.txt
-rw-r--r--  1 Laurent Aucun       3 11 nov.  17:48  o_letter.txt
-rw-r--r--  1 Laurent Aucun      13 11 nov.  17:48  f_letter.txt
-rw-r--r--  1 Laurent Aucun       8 11 nov.  17:48  v_letter.txt
-rw-r--r--  1 Laurent Aucun       8 11 nov.  17:48  q_letter.txt
-rw-r--r--  1 Laurent Aucun       2 11 nov.  17:48  b_letter.txt

This is the file generated for letter “a”:

$ cat a_letter.txt
array
a
array:
as
available

Dispatch Tables in Raku

We do more or less the same thing as in P5: we first write a function_builder subroutine that acts as a function factory. It receives a letter as a parameter, creates a file name for that letter, opens the corresponding file in write mode, and it returns an anonymous code block (actually a closure) that writes its argument to the file handle. This anonymous code block will be stored into the dispatch table.

In the MAIN subroutine , the program reads the words of the input file, fold them to lower case, and finds the first character of each such word. To avoid problems with special characters, we only keep words starting with a letter. If the dispatch table has no entry yet for this letter, the program calls function_builder subroutine to open the proper file and stores the code reference returned by that subroutine in the dispatch table. Finally, the program calls the code reference stored in the dispatch table for word’s first letter.

use v6;

sub function_builder (Str $letter) {
    my $file_name = "letter_$letter.txt";
    my $fh = open "./$file_name", :w;
    return { $fh.say($^a) }
}

multi sub MAIN (Str $file where *.IO.f) {
    my %dispatch;
    for $file.IO.words.map({.lc}) -> $word {
        my $letter = substr $word, 0, 1;
        next if $letter !~~ /^<[a..z]>/; 
        %dispatch{$letter} = function_builder $letter unless defined %dispatch{$letter};
        %dispatch{$letter}($word);
    }
}

Running the program and passing it the hash_slices.p6 file (the script of task # 1 of this week) produced the following files in the default directory:

-rwxr-xr-x  1 Laurent Aucun       5 11 nov.  18:26  letter_u.txt
-rwxr-xr-x  1 Laurent Aucun       5 11 nov.  18:26  letter_v.txt
-rwxr-xr-x  1 Laurent Aucun       3 11 nov.  18:26  letter_c.txt
-rwxr-xr-x  1 Laurent Aucun       6 11 nov.  18:26  letter_q.txt
-rwxr-xr-x  1 Laurent Aucun       5 11 nov.  18:26  letter_e.txt
-rwxr-xr-x  1 Laurent Aucun      72 11 nov.  18:26  letter_s.txt
-rwxr-xr-x  1 Laurent Aucun      29 11 nov.  18:26  letter_m.txt
-rwxr-xr-x  1 Laurent Aucun      18 11 nov.  18:26  letter_j.txt
-rwxr-xr-x  1 Laurent Aucun      19 11 nov.  18:26  letter_l.txt
-rwxr-xr-x  1 Laurent Aucun      13 11 nov.  18:26  letter_h.txt
-rwxr-xr-x  1 Laurent Aucun       8 11 nov.  18:26  letter_d.txt
-rwxr-xr-x  1 Laurent Aucun      22 11 nov.  18:26  letter_a.txt

This is the file generated for letter “a”:

$ cat letter_a.txt
array
a
array:
as

Wrapping up

The next week Perl Weekly Challenge is due to 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 Sunday, November, 24. And, please, also spread the word about the Perl Weekly Challenge if you can.

Perl Weekly Challenge 33: Count letters and Multiplication Tables

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

Spoiler Alert: This weekly challenge deadline is due in a few days from now (November 10,, 2019). This blog post offers some solutions to this challenge, please don't read on if you intend to complete the challenge on your own.

Challenge # 1: Count Letters (A..Z)

Create a script that accepts one or more files specified on the command-line and count the number of times letters appeared in the files.

So with the following input file sample.txt:

The quick brown fox jumps over the lazy dog.

the script would display something like:

a: 1
b: 1
c: 1
d: 1
e: 3
f: 1
g: 1
h: 2
i: 1
j: 1
k: 1
l: 1
m: 1
n: 1
o: 4
p: 1
q: 1
r: 2
s: 1
t: 2
u: 2
v: 1
w: 1
x: 1
y: 1
z: 1

This is not specified explicitly, but from the example, we gather that what is desired here is a case-insensitive letter count (in the example, both "T" and "t" count as "t"). So we will apply the lc (lower case) built-in function to the input.

Letter Histogram in Perl 5

We will start with a Perl 5 one-liner with one intersection.pl file as input:

$ perl -nE 'for my $l (split //, lc) { $h{$l}++}; END{say "$_: ", $h{$_}//0 for ("a".."z");}' intersection.pl
a: 96
b: 46
c: 25
d: 22
e: 72
f: 19
g: 20
h: 4
i: 77
j: 0
k: 0
l: 21
m: 16
n: 59
o: 32
p: 12
q: 1
r: 52
s: 77
t: 49
u: 9
v: 19
w: 3
x: 15
y: 31
z: 0

The -n command line option will loop over the lines of the input file. The program uses a %h hash to store the letter count. Note that, at the end, the hash will contain counts for characters other than the 'a'..'z' range, but we don't really care, since we will print out only the letters of that range. Note that some letters (j, k, and z) weren't seen in the process, but the $h{$_}//0 syntax ensures that the value 0 will be printed for letters where the hash isn't defined. Also note that the (split //, lc) syntax makes it possible to fold each line to lowercase (lc defaults on $_ when there are no arguments), and split works on the lower-cased line, so that $l will take in turn each character of the input line, folded to lowercase when needed.

This is now the output for the same one-liner with several input files (the same intersection.pl file plus several histo* files):

$ perl -nE 'for my $l (split //, lc) { $h{$l}++}; END{say "$_: ", $h{$_}//0 for ("a".."z");}' intersection.pl histo*
a: 199
b: 154
c: 123
d: 111
e: 271
f: 99
g: 37
h: 49
i: 170
(... some output lines omitted for brevity ...)
u: 42
v: 26
w: 22
x: 20
y: 68
z: 9

If you prefer a real full-fledged Perl script, this may look like this:

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

my %histo;

while (<>) {
    chomp;
    my $line = lc;
    for my $letter (split //, $line) {
        $histo{$letter}++ if $letter =~ /[a-z]/;
    }
}
for my $key ("a".."z") {
    say "$key: ", $histo{$key} // 0;
}

This script outputs the same result as the one-liner above when given the same input (be it only one or several files).

Note that, here, the program filters the input characters and stores only letters in the %histo hash. This is just to make this filtering more explicit (and self-documenting), but this is not necessary for the program to work the same way.

Letter Histogram in Raku (formerly known as Perl 6)

Perl 6 has been renamed "Raku" in October 2019, so we will use that name from now on.

In Raku, we can use a Bag, named $histo, rather than a hash to easily implement an histogram. With just a little bit of work, we're able to populate the bag in just one statement, without any explicit loop. Also, if a letter does not exist in the $histo bag, the bag will report 0, so that we don't need any special code to avoid an undefined warning for such an edge case. All this makes the code much more concise than the Perl 5 counterpart.

use v6;

sub MAIN (*@files) {
    my $histo = (map {.IO.comb».lc}, @files).Bag;
    say "$_ : ", $histo{$_} for 'a'..'z';
}

Used with one input file, the program displays the following:

$ perl6 histo_let.p6 intersection.pl
a : 96
b : 46
c : 25
d : 22
e : 72
f : 19
g : 20
h : 4
i : 77
j : 0
k : 0
[... Lines omitted for brevity ...]
y : 31
z : 0

And it works similarly with several input files:

$ ./perl6 histo_let.p6 intersection.pl histo*
a : 199
b : 154
c : 123
d : 111
e : 271
f : 99
g : 37
h : 49
i : 170
j : 4
k : 11
[... Lines omitted for brevity ...]
y : 68
z : 9

Challenge # 2: Formatted Multiplication Table

Write a script to print 11x11 multiplication table, only the top half triangle.

x|   1   2   3   4   5   6   7   8   9  10  11
---+--------------------------------------------
1|   1   2   3   4   5   6   7   8   9  10  11
2|       4   6   8  10  12  14  16  18  20  22
3|           9  12  15  18  21  24  27  30  33
4|              16  20  24  28  32  36  40  44
5|                  25  30  35  40  45  50  55
6|                      36  42  48  54  60  66
7|                          49  56  63  70  77
8|                              64  72  80  88
9|                                  81  90  99
10|                                     100 110
11|                                         121

Formatted Multiplication Table in Perl 5

It might make sense to write separate subroutines for headers and for lines of the multiplication table, but this is so simple that I tend to consider this overkill. I will rather print the header and then print the table lines. Perl has a format feature that I have used so rarely that I hardly remember how to use it. Besides, as far as I can say, it would not be very practical for such output. Even though I haven't written any large amount of C code for more than 15 years, I still like quite a lot the possibilities offered by the standard C printf function. For a nice formatted output, the simplest will be to use when needed the built-in Perl printf subroutine, which is almost the same as its C counterpart.

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

sub print_table {
    my $max = shift;
    # Print header
    printf "%2s |", "x";
    printf "%4d", $_ for 1..$max;
    say "\n---|", "-" x (4 * $max);
    # Print table lines
    for my $i (1..$max) {
        printf "%2d |%s", $i, ' ' x (4 * ($i - 1));
        for my $j ($i..$max) {
            printf "%4d", $i * $j;
        }
        say "";
    }
}
print_table shift//11;

Running this program with the default 11 value produces the following output:

$ perl mult-table.pl
 x |   1   2   3   4   5   6   7   8   9  10  11
---|--------------------------------------------
 1 |   1   2   3   4   5   6   7   8   9  10  11
 2 |       4   6   8  10  12  14  16  18  20  22
 3 |           9  12  15  18  21  24  27  30  33
 4 |              16  20  24  28  32  36  40  44
 5 |                  25  30  35  40  45  50  55
 6 |                      36  42  48  54  60  66
 7 |                          49  56  63  70  77
 8 |                              64  72  80  88
 9 |                                  81  90  99
10 |                                     100 110
11 |                                         121

You can also pass a larger value:

$ perl mult-table.pl 15
 x |   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
---|------------------------------------------------------------
 1 |   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15
 2 |       4   6   8  10  12  14  16  18  20  22  24  26  28  30
 3 |           9  12  15  18  21  24  27  30  33  36  39  42  45
 4 |              16  20  24  28  32  36  40  44  48  52  56  60
 5 |                  25  30  35  40  45  50  55  60  65  70  75
 6 |                      36  42  48  54  60  66  72  78  84  90
 7 |                          49  56  63  70  77  84  91  98 105
 8 |                              64  72  80  88  96 104 112 120
 9 |                                  81  90  99 108 117 126 135
10 |                                     100 110 120 130 140 150
11 |                                         121 132 143 154 165
12 |                                             144 156 168 180
13 |                                                 169 182 195
14 |                                                     196 210
15 |                                                         225

Note that this is not exactly the output shown in the task description, but this is deliberately so, I think this looks slightly better.

Formatted Multiplication Table in Raku (Perl 6)

Just as in Perl 5, the simplest is to use the printf subroutine when needed (I actually wrote the Raku version before the P5 one, but that's not important). The Raku program is very similar to the Perl 5 program:

use v6;
sub MAIN (UInt $max = 11) {
    print-table($max);
}
sub print-table ($max) {
    # Print header
    printf "%2s |", "x";
    printf "%4d", $_ for 1..$max;
    say "\n---|", "-" x 4 * ($max);
    # Print table lines
    for 1..$max -> $i {
        printf "%2d |%s", $i, ' ' x 4 * ($i - 1);
        for $i..$max -> $j {
            printf "%4d", $i * $j;
        }
        say "";
    }
}

This script prints out the following:

$ perl6 mult-table.p6
 x |   1   2   3   4   5   6   7   8   9  10  11
---|--------------------------------------------
 1 |   1   2   3   4   5   6   7   8   9  10  11
 2 |       4   6   8  10  12  14  16  18  20  22
 3 |           9  12  15  18  21  24  27  30  33
 4 |              16  20  24  28  32  36  40  44
 5 |                  25  30  35  40  45  50  55
 6 |                      36  42  48  54  60  66
 7 |                          49  56  63  70  77
 8 |                              64  72  80  88
 9 |                                  81  90  99
10 |                                     100 110
11 |                                         121

As for the P5 implementation, this is not exactly the output shown in the task description, but, as said before, I think this looks slightly better.

Just in case you want to know, this works equally well when passing a parameter other than 11. For example with an argument of 15, this prints the same as the P5 version.

Of course, the nice formatting starts to break when passing a parameter higher than 31, but the initial requirement was just an 11*11 multiplication table. It would not be difficult to change the script to make it work with larger values (we could even dynamically adapt the formatting strings to the maximal output number), but nobody needs commonly a larger multiplication table. Besides, it would print very badly with the width limit imposed by this site.

Wrapping up

The next week Perl Weekly Challenge is due to 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 Sunday, November, 17. And, please, also spread the word about the Perl Weekly Challenge if you can.

Perl Weekly Challenge 32: Word Histogram and ASCII Bar Chart

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

Spoiler Alert: This weekly challenge deadline is due in a few days (November 3, 2019). This blog post offers some solutions to this challenge, please don’t read on if you intend to complete the challenge on your own.

This week, both tasks were contributed by Neil Bowers.

Task # 1: Word Histogram

Create a script that either reads standard input or one or more files specified on the command-line. Count the number of times and then print a summary, sorted by the count of each entry.

So with the following input in file example.txt:

apple
banana
apple
cherry
cherry
apple

the script would display something like:

apple     3
cherry    2
banana    1

For extra credit, add a -csv option to your script, which would generate:

apple,3
cherry,2
banana,1

In other words, we’re supposed to make an histogram reporting the frequency of various words in the input.

Word Histogram in Perl 5

It is just a matter of collecting the frequency data in a %histo hash and then sort and printing the values.

#!/usr/bin/perl
use strict;
use warnings;

my %histo;
while (<>) {
    chomp;
    s/\s+$//;
    next if /^\s*$/; # skipping empty lines
    $histo{$_}++;
}
for my $key (sort { $histo{$b} <=> $histo{$a} } keys %histo) {
    printf "%-20s%d\n", $key, $histo{$key};
}

We can use the shell echo command to pipe some values into the script standard input:

$ echo 'apple
> banana
> apple
> cherry
> cherry
> apple' | perl word_histo.pl
apple               3
cherry              2
banana              1

CSV Extra Credit

For the extra credit, I’ll first create an actual word_test.txt test file:

$ cat word_test.txt
apple
banana
apple
cherry
cherry
apple

The new script will take a first parameter (0 or 1) to determine if the output should be fixed columns as before or CSV. The other parameter(s) will be one or several word files. And, for such a simple CSV, I’ll just do it manually and simply use two different formatting strings for printf. I know some people are adamant on using a CSV module, not me (well, at least, not for such a simple case): no one needs a 40-ton truck to deliver a book shipped by Amazon somewhere in a suburb or in the countryside.

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

my %histo;
my $csv_flag = shift;

while (<>) {
    chomp;
    s/\s+$//;
    next if /^\s*$/; # skipping empty lines
    $histo{$_}++;
}
my $format = $csv_flag ? "%s,%d\n" : "%-20s%d\n";

for my $key (sort { $histo{$b} <=> $histo{$a} } keys %histo) {
    printf $format, $key, $histo{$key};
}

Now, running the script with two file parameters (actually twice the name of the word_test.txt input file just created), once with the first parameter set to a false value (0) and once with it set to a true value (1) to get CSV output:

$ perl word_histo2.pl 0  word_test.txt word_test.txt
apple               6
cherry              4
banana              2

$ perl word_histo2.pl 1  word_test.txt word_test.txt
apple,6
cherry,4
banana,2

Word Histogram in Perl 6/Raku

In Perl 6/Raku, rather than using a hash, we can use a Bag to directly assign frequencies when reading the input files. Sorting the histogram can also be made simpler than in Perl 5: if the code block or subroutine passed to the sort built-in funtion accepts only one parameter, then this code block is not a comparison block or subroutine, but a code object implementing the transformation to be applied to the items to be sorted before using the default cmp comparison routine. Here, the {$histo{$_}} code block passed to the sortfunction, says that sort should apply the standard cmp comparison routine to the values associated with the keys that we want to sort. In addition, the P6/Raku cmp comparison routine and sort built-in function are clever enough to see that they are comparing integers and should therefore apply a numeric sort to the data.

use v6;

sub MAIN (*@files) {
    my $histo = @files.map({.IO.lines}).Bag;
    for reverse sort {$histo{$_}}, keys $histo -> $key {
        printf "%-20s%d\n", $key, $histo{$key};
    }
}

If you prefer another syntax, the histo assignment at the beginning could also be written as follows:

my $histo = (map {.IO.lines}, @files).Bag;

This program correctly takes into account the files passed as a parameter. For example, passing twice the same word_test.txt input file as before in P5:

$ perl6 word_histo.p6 word_test.txt word_test.txt
apple               6
cherry              4
banana              2

Note that there is (in Perl 6.d) a new IO.CatHandle class for seamlessly gathering input from multiple files, but this did not appear to be necessary here.

Extra Credit: CSV Option

For the extra credit, we could just try to add an optional parameter (with a default value), a Boolean flag to decide whether we want CSV output, and then change the printf formatting string according to its value:

sub MAIN (Int $csv = 0, *@files) { # ...

but that does not really work as expected when no CSV flag argument is passed to the program. It appears that an optional parameter cannot be put before a mandatory one. Changing the order of the arguments does not help, because an optional parameter cannot be put after variadic parameters.

We will therefore use two multi MAIN subroutines to handle cases where a Boolean flag is passed and those where there no such flag. These MAIN subroutines will populate a $*format dynamic scope variable and then call the same readfiles subroutine:

use v6;
subset file of Str where *.IO.f;

multi sub MAIN (Int $csv, *@files where all(@files) ~~ file) {
    my $*format = $csv ?? "%s,%d\n" !! "%-20s%d\n";
    readfiles @files;
}
multi sub MAIN (*@files where all(@files) ~~ file) {
    my $*format = "%-20s%d\n";
    readfiles @files;
}
sub readfiles (@files) {
    my $histo = @files.map({.IO.lines}).Bag;
    for reverse sort {$histo{$_}}, keys $histo -> $key {
        printf $*format, $key, $histo{$key};
    }
}

This can be tested with or without a CSV flag:

$ perl6 word_histo2.p6 word_test.txt word_test.txt
apple               6
cherry              4
banana              2

$ perl6 word_histo2.p6 1 word_test.txt word_test.txt
apple,6
cherry,4
banana,2

$ perl6 word_histo2.p6 0 word_test.txt word_test.txt
apple               6
cherry              4
banana              2

Using Named Parameters

So, now, this works properly, but we may still have a slight problem if the name of the file passed as an argument is a plain integer: this would become ambiguous, and the Moar virtual machine might not be able to tell an integer from a file. This can be solved with named arguments for the Boolean CSV flag, which will also make it possible to write shorter and simpler code:

use v6;
subset file of Str where *.IO.f;

sub MAIN (Bool :$csv, *@files where all(@files) ~~ file) {
    my $format = $csv ?? "%s,%d\n" !! "%-20s%d\n";
    my $histo = @files.map({.IO.lines}).Bag;
    for reverse sort {$histo{$_}}, keys $histo -> $key {
        printf $format, $key, $histo{$key};
    }
}

Now, we need to pass a --csv argument when calling the program at the CLI in order to activate the CSV format:

$ perl6 word_histo2.p6 word_test.txt word_test.txt
apple               6
cherry              4
banana              2

$ perl6 word_histo2.p6 --csv word_test.txt word_test.txt word_test.txt
apple,9
cherry,6
banana,3

Task 2: ASCII Bar Chart

Write a function that takes a hashref where the keys are labels and the values are integer or floating point values. Generate a bar graph of the data and display it to stdout.

The input could be something like:

$data = { apple => 3, cherry => 2, banana => 1 };
generate_bar_graph($data);

And would then generate something like this:

 apple | ############
cherry | ########
banana | ####

If you fancy then please try this as well: (a) the function could let you specify whether the chart should be ordered by (1) the labels, or (2) the values.

ASCII Bar Chart in Perl 5

There is really nothing complicated in generating the bars of the chart: we just need to use the x string repetition operator with the fruit values. However, I would like to standardize somehow the size of output, irrespective of the absolute values. For this, the program loops over the hash a first time to collect the minimum and maximum values, and computes a scaling factor as 10 / ($max - $min), and then uses that $scale_factor for standardizing the length of the bars, so that the bar graph has about the same size for values of 4, 6, and 9 as for values of 40, 60 and 90. The hard coded value of 10 arbitrarily chosen here simply means that the spread between the smallest and the largest value will be represented by 10 units (concretely, 10 # characters). I could have chosen another value, but I wanted the bar graphs to keep relatively small to make sure they remain correctly formatted within the limited page width of this blog post.

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

sub generate_chart {
    my %data = %{$_[0]};
    my ($max, $min);
    for my $key (keys %data) {
        ($max, $min) = ($data{$key}, $data{$key}) unless defined $max;
        $max = $data{$key} if $data{$key} > $max;
        $min = $data{$key} if $data{$key} < $min;
    }
    my $scale_factor = 10 / ($max - $min);
    for my $key (sort { $data{$b} <=> $data{$a} } keys %data) {
        printf "%15s | %s\n", $key, "#" x ($data{$key} * $scale_factor);
    }
}
my $data = { apple => 30, cherry => 60, banana => 10, pear => 40 };
generate_chart $data;

This generates the following output:

$ perl ascii_chart.pl
         cherry | ############
           pear | ########
          apple | ######
         banana | ##

With this scaling, if we now use the following hashref with all values ten times smaller:

my $data = { apple => 3, cherry => 6, banana => 1, pear => 4 };

the program generates more or less the same output (there may occasionally be some slight rounding differences):

$ perl ascii_chart.pl
         cherry | ############
           pear | ########
          apple | ######
         banana | ##

Ordering the Bar Chart in Accordance with Labels or Values

For ordering the bar chart in accordance with labels or values, we could simply have two for loops for printing out the bar chart and use one or the other loop depending on the ordering we selected. But that’s code repetition, and I don’t like to do that for numerous reasons, the main one being that, sometimes in the future, a person in charge of maintaining the project is likely to modify one of the loops and forget to modify the other accordingly. So let’s try to keep it DRY (“don’t repeat yourself”).

The solution suggested here uses a $sort_routine variable containing an anonymous subroutines as a first argument to the sortbuilt-in function. Depending on the $sort_type (label or value) passed to the program, the $sort_routine code reference will contain different code (value will be the default if no argument is passed):

    my $sort_routine = ($sort_type =~ /val/i) 
        ? sub { $data{$b} <=> $data{$a} } 
        : sub {$a cmp $b };

The full program now looks like this:

use strict;
use warnings;
use feature qw/say/;

sub generate_chart {
    my %data = %{$_[0]};
    my $sort_type = $_[1] // "val";
    my ($max, $min);
    for my $key (keys %data) {
        ($max, $min) = ($data{$key}, $data{$key}) unless defined $max;
        $max = $data{$key} if $data{$key} > $max;
        $min = $data{$key} if $data{$key} < $min;
    }
    my $scale_factor = 10 / ($max - $min);
    my $sort_routine = ($sort_type =~ /val/i) 
        ? sub { $data{$b} <=> $data{$a} } 
        : sub {$a cmp $b }; 
    for my $key (sort $sort_routine keys %data) {
        printf "%15s | %s\n", $key, "#" x ($data{$key} * $scale_factor);
    }
}
my $sort_type = shift;
my $data = { cherry => 20, apple => 30,  banana => 10, pear => 25};
generate_chart $data, $sort_type;

This is the output generated with various arguments passed to the program:

$ perl ascii_chart2.pl
          apple | ###############
           pear | ############
         cherry | ##########
         banana | #####

$ perl ascii_chart2.pl value
          apple | ###############
           pear | ############
         cherry | ##########
         banana | #####

$ perl ascii_chart2.pl label
          apple | ###############
         banana | #####
         cherry | ##########
           pear | ############

ASCII Bar Chart in Perl 6/Raku

For a start, we will use the same approach as in Perl 5 to scale the bar graph:

use v6;

sub generate_chart (%data) {
    my ($max, $min);
    for keys %data -> $key {
        ($max, $min) = (%data{$key}, %data{$key}) unless defined $max;
        $max = %data{$key} if %data{$key} > $max;
        $min = %data{$key} if %data{$key} < $min;
    }
    my $scale_factor = 10 / ($max - $min);
    for sort { %data{$^b} <=> %data{$^a} }, keys %data -> $key {
        printf "%15s | %s\n", $key, "#" x (%data{$key} * $scale_factor);
    }
}
my $data = { apple => 3, cherry => 6, banana => 1, pear => 4 };
generate_chart $data;

Note that Perl 6/Raku has no real difference between hashes and hash references in most cases.

This produces output similar to what we had in P5:

$ perl6 ascii_chart.p6
         cherry | ############
           pear | ########
          apple | ######
         banana | ##

Ordering the Bar Chart in Accordance with Labels or Values

As in Perl 5, we will use anonymous code references as the first argument to the sort built-in function.

use v6;

sub generate_chart (%data) {
    my ($max, $min);
    for keys %data -> $key {
        ($max, $min) = (%data{$key}, %data{$key}) unless defined $max;
        $max = %data{$key} if %data{$key} > $max;
        $min = %data{$key} if %data{$key} < $min;
    }
    my $scale_factor = 10 / ($max - $min);
    my &sort_routine = ($*sort-type ~~ m:i/val/) 
        ?? { %data{$^b} <=> %data{$^a} } 
        !! {$^a cmp $^b }; 
    for sort &sort_routine, keys %data -> $key {
        printf "%15s | %s\n", $key, "#" x (%data{$key} * $scale_factor);
    }
}
sub MAIN (Str $*sort-type) {
    my $data = { apple => 3, cherry => 6, banana => 1, pear => 4 };
    generate_chart $data;
}

This works as expected:

$ perl6 ascii_chart2.p6 val
         cherry | ############
           pear | ########
          apple | ######
         banana | ##

$ perl6 ascii_chart2.p6 lab
          apple | ######
         banana | ##
         cherry | ############
           pear | ########

Wrapping up

The next week Perl Weekly Challenge is due to 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 Sunday, November 10, 2019. And, please, also spread the word about the Perl Weekly Challenge if you can.

Perl Weekly Challenge 31: Illegal Division by Zero and Dynamic Variables

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

Spoiler Alert: This weekly challenge deadline is due in a few days from now (October 27, 2019). This blog post offers some solutions to this challenge, please don't read on if you intend to complete the challenge on your own.

Challenge # 1: Illegal Division by Zero

Create a function to check divide by zero error without checking if the denominator is zero.

Illegal Division by Zero in Perl 5

Perl 5 has a number of modules to implement exception handling using the try ... catch pattern found in a number of other languages, such as, for example, Try::Tiny or TryCatch. Even Autodie might actually fit the bill. But, because this is a coding challenge, we prefer to avoid using modules that do the work you're supposed to do.

In fact, not doing anything special will check the division by zero, as shown in these one-liners:

$ perl -E 'say $ARGV[0] / $ARGV[1]' 2 4
0.5

$ perl -E 'say $ARGV[0] / $ARGV[1]' 2 0
Illegal division by zero at -e line 1.

In a way, this simple one-liner does check the divide by zero error. But, OK, maybe that's cheating a bit. So let's try to catch an error in this case.

Since I don't want to use modules here, I'll use the good old eval built-in function. The eval function has two forms (string and block). The string version is sometimes frowned upon for various reasons (notably because it can be dangerous when used carelessly), but it can be very useful when properly used. Anyway, we'll be using here the block version that doesn't have such problems. This form is typically used to trap exceptions (which is what we need here), while also providing the benefit of checking the code within the eval block at compile time.

If there is a syntax error or runtime error, eval returns undef in scalar context, or an empty list in list context, and $@ is set to the error message. (Prior to 5.16, a bug caused undef to be returned in list context for syntax errors, but not for runtime errors. We're using here version 26 of Perl, so we don't care about this former bug which would not have annoyed us anyway in our context.) If there was no error, $@ is set to the empty string.

This is our program:

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

die "We need an input of two numbers\n" unless @ARGV == 2;
my ($numerator, $denominator) = @ARGV;
my $result;
eval {
    $result = $numerator / $denominator;
};
die "$@" if $@;
say "Result of division is: $result";

Running this program with various input values produces the following output:

$ perl illegal_div.pl
We need an input of two numbers

$ perl illegal_div.pl 32
We need an input of two numbers

$ perl illegal_div.pl 32 8
Result of division is: 4

$ perl illegal_div.pl 32 0
Illegal division by zero at illegal_div.pl line 10.

Illegal Division by Zero in Perl 6 (or Raku)

Perl 6 has very rich error handling features, most notably the Exception class. Without going into all the lengthy details, let us say that it's possible to handle exceptional circumstances by supplying a CATCH block. To solve the challenge can be as simple as this:

use v6;

sub MAIN (Numeric $numerator, Numeric $denominator) {
    say "Result of division is: ", $numerator / $denominator;
    CATCH {
        say $*ERR: "Something went wrong here: ", .Str;
        exit; 
    }
}

Using this script first with legal parameters and then with an illegal 0 denominator produces the following output:

$ perl6 try-catch.p6  8 4
Result of division is: 2

$ perl6 try-catch.p6  8 0
Something went wrong here: Attempt to divide by zero when coercing Rational to Str

An exception object is usually contained in the $! special variable, but a CATCH block topicalizes the exception object, meaning that it becomes available in the $_ topical variable (hence the .Str syntax is sufficient to obtain the description of the exception).

Although it is not really needed here, it may sometimes be useful to define the scope of the CATCH block by enclosing it in a try block, for example:

use v6;

sub MAIN (Numeric $numerator, Numeric $denominator) {
    try {
        say "Result of division is: ", $numerator / $denominator;
        CATCH {
            say $*ERR: "Something went wrong here: ", .Str;
            exit; 
        }
    }
}

Actually, defining a try block creates an implicit CATCH block, and this may be used to contain the exception:

use v6;

sub MAIN (Numeric $numerator, Numeric $denominator) {
    try {
        say "Result of division is: ", $numerator / $denominator;
    }
}

The above program does not die and doesn't print anything but exits normally (with the successful exit code, 0, on Unix-like systems) when you pass a zero value for the denominator. We're in effect silencing the exception. Even if you don't want to abort the program when encountering such an error, you might still prefer to tell the user that something went wrong with a message containing the description of the caught exception:

use v6;

sub MAIN (Numeric $numerator, Numeric $denominator) {
    try {
        say "Result of division is: ", $numerator / $denominator;
    } or say "Houston, we've had a problem here: ",  $!.Str;
}

which outputs the following:

$ perl6 try-catch.p6  8 4
Result of division is: 2

$ perl6 try-catch.p6  8 0
Houston, we've had a problem here: Attempt to divide by zero when coercing Rational to Str

Dynamic Variable Name

Create a script to demonstrate creating dynamic variable name, assign a value to the variable and finally print the variable. The variable name would be passed as command line argument.

There are some scripting languages (such as various Unix shells) where it is possible to dynamically create variable names. This is sometimes useful, but it tends to mess up the script's name space.

If I understand the task well, we're requested to use symbolic references, as this is probably the only way to dynamically create variable names in Perl. I must warn you: Symbolic references are evil. Don't use them in Perl. There are better ways, as we will see later.

I could spend quite a bit of time explaining why they are bad, but Mark-Jason Dominus, the author of Higher Order Perl (an excellent book BTW), has already done it much better that I could probably ever do. Please read Mark-Jason's article in three installments on the subject:

Dynamic Variable Name in Perl 5

If you're using use strict; (and you always use this pragma, right?), you will not be able to use symbolic references and you'll get this type of error:

Can't use string ("foo") as a SCALAR ref while "strict refs" in use at sym_ref.pl line 12.

There are good reasons for that. Symbolic references were quite common in Perl 4 (which was replaced by Perl 5 more than 25 years ago) and they have not been removed completely from Perl 5 in the name of backward compatibility. That's why it is still possible (but highly deprecated) to use them. But they are never needed in Perl 5. With the strict pragma, you're forbidden to use symbolic references since it can be safely assumed that you're not using Perl 4 and they are bad in Perl 5. You'll need to disable part of the Strict benefits to use symbolic references.

In other words, the first thing you need to do if you really want to shoot yourself in the foot and use symbolic references is to disable strict references with the pragma no strict 'refs'; (but again, you really shouldn't be doing that). I hate to have to show this, but, then you can (but really shouldn't) use the variable name as a variable:

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';
# DON'T DO THIS
no strict 'refs'; # Needed for allowing symbolic references

@ARGV == 2 or die "Please supply two parameters.";
my ($var_name, $var_content) = @ARGV;

# This is bad, don't do it!
$$var_name = $var_content;
say "The variable is called $var_name and its value is $$var_name";

And this works as expected:

$ perl sym_ref.pl foo bar
The variable is called foo and its value is bar

But it is dangerous, for the reasons well explained by Mark-Jason Dominus. Sometimes, I say on forums things like this: "You should probably not use subroutines prototypes unless you really know what you're doing." In the case of symbolic references, I would be more adamant: don't do that, probably even if you think you really know what you're doing.

Note that we have used the eval function in the first task of this challenge. It is also be possible to create dynamic variable names using eval (without using no strict 'refs';), but it is IMHO at least as bad, perhaps even worse, so don't do this either. We will see now how to obtain the same result cleanly.

A Much Better Solution

If you're using symbolic references, you are in fact messing under the hood with a quite special global hash, the symbol table or a lexical pad. It is always far better to use a regular lexical hash (or sometimes a hash of hashes). For example, in our case, a very simple hash:

#!/usr/bin/perl

use strict;
use warnings;
use feature 'say';


@ARGV == 2 or die "Please supply two parameters.";
my %hash;
my ($name, $content) = @ARGV;
$hash{$name} = $content;
say "The item is called $name and its value is $hash{$name}";

This program displays the name of the item and its value:

$ perl sym_ref_fixed.pl foo bar
The item is called foo and its value is bar

Dynamic Variable Name in Perl 6 (Raku)

I do not think that there is anything like symbolic references in Perl 6. So, it seems that it is not possible to literally "demonstrate creating dynamic variable name" in Perl 6. What we can do, however, is to replicate the much better P5 solution and use a hash:

use v6;

sub MAIN (Str $name, Str $value) {
    my %hash = $name => $value;
    say "The item is called $name and its value is %hash{$name}";
}

This program displays the name of the item and its value:

$ perl6 sym_ref.p6 foo bar
The item is called foo and its value is bar

Wrapping up

The next week Perl Weekly Challenge is due to 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 Sunday, November, 3. And, please, also spread the word about the Perl Weekly Challenge if you can.

Perl Weekly Challenge 30: Sunday Christmas and Triplets

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

Spoiler Alert: This weekly challenge deadline is due in a few days from now (October 20, 2019). This blog post offers some solutions to this challenge, please don't read on if you intend to complete the challenge on your own.

Challenge # 1: Sunday Christmas

Write a script to list dates for Sunday Christmas between 2019 and 2100. For example, 25 Dec 2022 is Sunday.

Christmas on Sunday in Perl 5

I'll be using the Time::Local core module which provides reciprocal functions of the gmtime and localtime built-in functions.

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

say "Years during which Christmas falls on a Sunday:";
for my $year (119..200) {
    my $date = timegm(0, 0, 0, 25, 11, $year);
    say $year + 1900 if (gmtime $date)[6] == 0;
}

Note that both the built-in gmtime and the module timegm functions count the year from 1900 upward (so that 2019 should be input as 119) and start the month count at 0, so that December is considered to be 11.

The above program displays the following:

Years during which Christmas falls on a Sunday:
2022
2033
2039
2044
2050
2061
2067
2072
2078
2089
2095

We could also do it as a (slightly long) one-liner:

$ perl -MTime::Local -E 'say join " ", map {(gmtime $_)[5] + 1900}  grep { (gmtime $_)[6] == 0 } map {timegm(0, 0, 0, 25, 11, $_)} 119..200;'
2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095

Christmas on Sunday in Perl 6

In Perl 6, the Date data type offers the built-in methods we need for date computations, including finding day of week.

use v6;
for 2019..2100 -> $year {
    say "Christmas of year $year falls on a Sunday." 
        if Date.new($year, 12, 25).day-of-week == 7;
}

which duly prints out:

Christmas of year 2022 falls on a Sunday.
Christmas of year 2033 falls on a Sunday.
Christmas of year 2039 falls on a Sunday.
Christmas of year 2044 falls on a Sunday.
Christmas of year 2050 falls on a Sunday.
Christmas of year 2061 falls on a Sunday.
Christmas of year 2067 falls on a Sunday.
Christmas of year 2072 falls on a Sunday.
Christmas of year 2078 falls on a Sunday.
Christmas of year 2089 falls on a Sunday.
Christmas of year 2095 falls on a Sunday.

We could also do it in the form of a Perl 6 one-liner:

$ perl6 -e 'say grep {Date.new($_, 12, 25).day-of-week == 7}, 2019..2100;'
(2022 2033 2039 2044 2050 2061 2067 2072 2078 2089 2095)

Integer Triplets Whose Sum is 12

Write a script to print all possible series of 3 numbers, where in each series at least one of the number is even and sum of the three numbers is always 12. For example, 3,4,5.

This is not specified, but we will consider that all three numbers should be strictly positive (i.e. larger than or equal to 1), because if we were to admit 0 as one of the numbers, it would no longer be a real triplet (in the context of addition). A consequence is that the largest number that can be used is 10 (to obtain 12 when adding twice 1).

Integer Triplets in Perl 5

We will use three nested loops for visiting all possibilities for the three numbers. However, we don't want to obtain duplicate triplets such as (1, 2, 9), (2, 1, 9), (9, 1, 2), etc., which are all the same. Therefore, when looping on the second number, we will loop from the first number to 10, and similarly for the third number. Thus, each triplet will be in (non strict) ascending order and won't get any duplicate.

We also need at least one of the three numbers to be even; for that, we can check whether the product of the three numbers is even (more on this later).

Our first (somewhat naïve) implementation could be as follows:

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

for my $i (1..10) {
    for my $j ($i..10) {
        last if $i + $j > 11;
        for my $k ($j..10) {
            next unless $i * $j * $k % 2 == 0; # Check 1 number is even
            my $sum = $i + $j + $k;
            last if $sum > 12;
            say "$i, $j, $k" if $sum == 12;
        }
    }
}

This program prints the following correct result:

$ perl triplet.pl
1, 1, 10
1, 2, 9
1, 3, 8
1, 4, 7
1, 5, 6
2, 2, 8
2, 3, 7
2, 4, 6
2, 5, 5
3, 3, 6
3, 4, 5
4, 4, 4

But we're doing a bit too much work here when we check whether one of the numbers is even. The only case where none of the numbers of a triplet is even is when all three numbers are odd, and the sum of three odd integers cannot be 12 (and, more generally, cannot be an even number). So, we simply don't need to check that one number is even: checking that the sum of the 3 numbers if 12 is sufficient to prove that one at least of the three numbers is even.

So we can rewrite the nested loops as follows:

for my $i (1..10) {
    for my $j ($i..10) {
        last if $i + $j > 11;
        for my $k ($j..10) {
            my $sum = $i + $j + $k;
            last if $sum > 12;
            say "$i, $j, $k" if $sum == 12;
        }
    }
}

And this new version produces the same output.

Integer Triplets in Perl 6

We've seen before that we don't need to check that one of the numbers is even.

For solving this problem in Perl 6, we would like to use the X cross product operator in order to generate all possible triplets and then keep those whose sum is 12.

But if we do something like this:

for 1..10 X 1..10 X 1..10 -> $triplet {
    next unless ([+] | $triplet) == 12;
    say $triplet;
}

we obtain duplicate triplets:

...
(1 2 9)
...
(2 1 9)
...
(2 9 1)
...
(9 1 2)
(9 2 1)
...

We can get rid of this problem by keeping only triplets in which the numbers are in (non strict) ascending order:

use v6;
for 1..10 X 1..10 X 1..10 -> $triplet {
    next unless [<=] | $triplet;  # ascending order
    say $triplet if 12 == [+] $triplet;
}

which produces the desired result:

$ perl6 triplets.p6
(1 1 10)
(1 2 9)
(1 3 8)
(1 4 7)
(1 5 6)
(2 2 8)
(2 3 7)
(2 4 6)
(2 5 5)
(3 3 6)
(3 4 5)
(4 4 4)

Wrapping up

The next week Perl Weekly Challenge is due to 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 Sunday, October, 27. And, please, also spread the word about the Perl Weekly Challenge if you can.