Square Secret Code

This post is part of a series on Mohammad Anwar’s excellent Perl Weekly Challenge, where Perl and Raku hackers submit solutions to two different challenges every week. (It’s a lot of fun, if you’re into that sort of thing.)

Task #1 this week is a simple cipher, described as follows:

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.

Given “The quick brown fox jumps over the lazy dog”, the expected result is “tbjrd hruto eomhg qwpe unsl ifoa covz kxey”.

Perl

In Perl, we can use a couple of temp variables, one for the current index, and the other is an array of the 8 strings we will build up on our way through the plaintext:

use constant COLUMNS => 8;

sub encode {
    local $_ = lc shift;
    s/\s//g;
    my ($i, @s);

    map { $s[$i++ % COLUMNS] .= $_ } split '';

    join ' ', @s;
}

Modulo arithmetic ensures we append one character to each string in rotation.

Raku

In Raku, it’s even easier:

sub encode( Str $plain, Int $width = $plain.chars.sqrt.Int ) {
    my @s;
    $plain.lc.subst(/\s/,'',:g).comb.kv.map: { @s[$^i % $width] ~= $^str };

    @s.join(' ')
}

Here, I set a default for $width of the integer square root of the plaintext length. This gives a true “square” cipher, or the best we can, anyway. However, you can still override that to get the width of 8 specified in the challenge description, which is what I did in MAIN (not shown).

In Raku, we avoid the need for the temp $i variable thanks to kv giving us key/value pairs.

Leave a Reply

Your email address will not be published. Required fields are marked *