This post is part of a series on Mohammad Anwar’s excellent Weekly Challenge, where hackers submit solutions in Perl, Raku, or any other language, 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.