Perl Weekly Challenge 45: Square Secret Code and Source Dumper

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

Task # 1: Square Secret Code

The square secret code mechanism first removes any space from the original message. Then it lays down the message in a row of 8 columns. The coded message is then obtained by reading down the columns going left to right.

For example, the message is “The quick brown fox jumps over the lazy dog”.

Then the message would be laid out as below:

thequick
brownfox
jumpsove
rthelazy
dog

The code message would be as below:

tbjrd hruto eomhg qwpe unsl ifoa covz kxey

Write a script that accepts a message from command line and prints the equivalent coded message.

Square Secret Code in Perl

Let’s do a first program implementing the task exactly as described:

use strict;
use warnings;
use feature "say";

my $msg = shift // "The quick brown fox jumps over the lazy dog";
$msg =~ s/\s+//g;
$msg =~ s/(.{8})/$1\n/g;
my @lines = split /\n/, $msg;
for my $i (0..7) {
    print map { substr  $_, $i, 1 if length $_ >= $i} @lines;
    print " ";
}

This works as expected:

$ perl square.pl "The quick brown fox jumps over the lazy dog"
Tbjrd hruto eomhg qwpe unsl ifoa covz kxey

But we don’t really need to lay out the message over rows of 8 characters and can simplify a bit the code using an array of strings as follows:

use strict;
use warnings;
use feature "say";

my $msg = shift // "The quick brown fox jumps over the lazy dog";
$msg =~ s/\s+//g;
my @letters = map { /.{1,8}/g; } $msg;
for my $i (0..7) {
    print map { substr  $_, $i, 1 if length $_ >= $i} @letters;
    print " ";
}

This produces the same output as before.

Square Secret Code in Raku

Here, we’re just porting the second Perl version above:

use v6;

my $msg = @*ARGS ?? shift @*ARGS 
    !! "The quick brown fox jumps over the lazy dog";
$msg ~~ s:g/\s+//;
my @letters = map { ~ $_}, $msg ~~ m:g/ .**1..8/;
for 0..7 -> $i {
    print " ", join "", map { substr  $_, $i, 1 if .chars >= $i}, @letters;
    #print " ";
}

This displays the following output:

$ perl6 square.p6 "The quick brown fox jumps over the lazy dog"
 Tbjrd hruto eomhg qwpe unsl ifoa covz kxey

Task # 2: Source Dumper

Write a script that dumps its own source code. For example, say, the script name is ch-2.pl then the following command should return nothing.

$ perl ch-2.pl | diff - ch-2.pl

Source Dumper in Perl

In Perl, the $0 special variable contains the name of the program. So, it is just a matter of opening the file and printing its lines:

use strict;
use warnings;

my $progr = "./$0";
open my $IN, "<", $progr or die "Unable to open $progr $!";
print while <$IN>;
close $IN;

Running the program duly prints its contents:

$ perl pgm_dump.pl
use strict;
use warnings;

my $progr = "./$0";
open my $IN, "<", $progr or die "Unable to open $progr $!";
print while <$IN>;
close $IN;

And a diff between the program output and the program code prints out nothing:

$ perl pgm_dump.pl | diff - pgm_dump.pl

Source Dumper in Raku

In Raku, the program name (and path) is contained in the $?FILE compile-time variable. So solving the task is very easy:

use v6;

my $progr = "$?FILE";
$progr.IO.slurp.say;

which duly prints:

$ perl6 pgm_dump.p6
use v6;

my $progr = "$?FILE";
$progr.IO.slurp.say;

Actually, we don’t need the intermediate $progr variable:

use v6;

$?FILE.IO.slurp.say;

which also prints the expected output:

$ perl6 pgm_dump.p6
use v6;

$?FILE.IO.slurp.say;

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, February 9. 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.