Home > Raku > Antipairing

## Antipairing

As suspicious questions on IRC and Discord revealed, there are quite a few solutions to the PWC that are not made public. One question in particular indicates that there is a build-in missing in Raku.

Nemokosch: let’s say I have a 5×5 table for some reason

PWC162-2 is asking to implement an encryption algorithm that uses a simple substitution table. Having a data-struction that allowes to turn a character into a 2-dimensional `@index` and then use it to `@replacement[||@index]` would be very helpful indeed. We can use `.antipairs` to turn a simple list into something we can assign to a `Hash` and be done with it. With 2-dimension, we have to create our own.

``````proto sub deepantipairs(@positional, \$dimensions --> Positional) {*}
multi sub deepantipairs(@a, 2) {
@a.pairs.map({ my \$outer-key = .key; .value.antipairs.map({ .key => (\$outer-key, .value) }) }).flat
}
my \$phrase = 'Spring has sprung!';
my @table = flat(\$phrase.lc.comb.grep(/\w/), 'a'..'z').unique[^25].batch(5);
my %antitable = @table.&deepantipairs(2);

# OUTPUT:

# Array @table = [("S", "p", "r", "i", "n"), ("g", "h", "a", "s", "u"), ("!", "b", "c", "d", "e"), ("f", "j", "k", "l", "m"), ("o", "q", "t", "v", "w")]
# Hash %antitable = {"!" => \$(2, 0), :S(\$(0, 0)), :a(\$(1, 2)), :b(\$(2, 1)), :c(\$(2, 2)), :d(\$(2, 3)), :e(\$(2, 4)), :f(\$(3, 0)), :g(\$(1, 0)), :h(\$(1, 1)), :i(\$(0, 3)), :j(\$(3, 1)), :k(\$(3, 2)), :l(\$(3, 3)), :m(\$(3, 4)), :n(\$(0, 4)), :o(\$(4, 0)), :p(\$(0, 1)), :q(\$(4, 1)), :r(\$(0, 2)), :s(\$(1, 3)), :t(\$(4, 2)), :u(\$(1, 4)), :v(\$(4, 3)), :w(\$(4, 4))}``````

Let’s rotate the table (the basic idea behind the Enigma) to create a much more interesting cypher-text.

``````sub encrypt(\$phrase, \$text --> Str) {
my @table = flat(\$phrase.lc.comb.grep(/\w/), 'a'..'z').unique[^25].batch(5);
my %antitable = @table.&deepantipairs(2);

my \$retval;

for \$text.lc.comb.grep(/\w/) -> \$char {
my @deepindex := %antitable{\$char};
\$retval ~= @table[||@deepindex];
@table = @table».List.flat[1..*,0].flat.batch(5);
}

\$retval
}

say encrypt(\$phrase, 'As suspicious questions on IRC and Discord revealed, there are quite a few solutions to the PWC that are not made public. One question in particular indicates that there is a build-in in Raku missing.');

# OUTPUT:
As you likely spotted, I defined a `proto` with the argument `\$dimensions` (our item may be an `Iterable` so we can’t infer this argument). Raku has many very handy methods defined in `List` that work very well with a single dimension. There may be more work to do when we start to support fixed size shaped arrays well.