aboutsummaryrefslogtreecommitdiff
path: root/challenge-162
diff options
context:
space:
mode:
authorPaulo Custodio <pauloscustodio@gmail.com>2022-04-27 16:12:33 +0100
committerGitHub <noreply@github.com>2022-04-27 16:12:33 +0100
commit830204e938a5421f4d6d91d6cefcc48481da9dd2 (patch)
tree6964bdc53f46dc3d43c531eda6dc724491c6088a /challenge-162
parent736ca6ca1d398132bdae787a5dfbb1d15d573d75 (diff)
parent237ab4513c510cab55bb77473b79820e7b2d6da8 (diff)
downloadperlweeklychallenge-club-830204e938a5421f4d6d91d6cefcc48481da9dd2.tar.gz
perlweeklychallenge-club-830204e938a5421f4d6d91d6cefcc48481da9dd2.tar.bz2
perlweeklychallenge-club-830204e938a5421f4d6d91d6cefcc48481da9dd2.zip
Merge branch 'manwar:master' into master
Diffstat (limited to 'challenge-162')
-rw-r--r--challenge-162/dave-jacoby/blog.txt1
-rw-r--r--challenge-162/dave-jacoby/perl/ch-1.pl32
-rw-r--r--challenge-162/dave-jacoby/perl/ch-2.pl131
-rw-r--r--challenge-162/julien-fiegehenn/perl/ch-1.pl46
-rw-r--r--challenge-162/julien-fiegehenn/perl/ch-2.pl199
-rwxr-xr-xchallenge-162/luca-ferrari/raku/ch-1.p66
-rwxr-xr-xchallenge-162/luca-ferrari/raku/ch-2.p696
-rw-r--r--challenge-162/peter-campbell-smith/blog.txt1
-rwxr-xr-xchallenge-162/peter-campbell-smith/perl/ch-1.pl34
-rwxr-xr-xchallenge-162/peter-campbell-smith/perl/ch-2.pl133
-rw-r--r--challenge-162/robert-dicicco/perl/ch-1.pl28
-rw-r--r--challenge-162/robert-dicicco/raku/ch-1.raku22
12 files changed, 729 insertions, 0 deletions
diff --git a/challenge-162/dave-jacoby/blog.txt b/challenge-162/dave-jacoby/blog.txt
new file mode 100644
index 0000000000..6d9cddbe8c
--- /dev/null
+++ b/challenge-162/dave-jacoby/blog.txt
@@ -0,0 +1 @@
+https://jacoby.github.io/2022/04/26/play-fair-and-by-the-book-weekly-challenge-162.html
diff --git a/challenge-162/dave-jacoby/perl/ch-1.pl b/challenge-162/dave-jacoby/perl/ch-1.pl
new file mode 100644
index 0000000000..3c1b975c5b
--- /dev/null
+++ b/challenge-162/dave-jacoby/perl/ch-1.pl
@@ -0,0 +1,32 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use experimental qw{ say postderef signatures state };
+
+use List::Util qw{ sum0 };
+
+my @samples;
+push @samples, '978-0-306-40615-7'; # error-correction coding
+ # for digital communication
+push @samples, '978-0596001735'; # perl best practices
+push @samples, '978-0596003135'; # perl cookbook
+push @samples, '978-0596004927'; # programming perl
+push @samples, '978-1492094951'; # learning perl
+push @samples, '978-1680500882'; # modern perl
+
+for my $sample (@samples) {
+ my $check = find_check_digit($sample);
+ say <<"END";
+ ISBN-13: $sample
+ Check: $check
+END
+}
+
+sub find_check_digit( $isbn13) {
+ my @digits = $isbn13 =~ /(\d)/gmix;
+ pop @digits;
+ push @digits, 0;
+ my @x = map { $_ % 2 == 1 ? 3 * $digits[$_] : $digits[$_] } 0 .. 12;
+ return 10 - ( ( sum0 @x ) % 10 );
+}
diff --git a/challenge-162/dave-jacoby/perl/ch-2.pl b/challenge-162/dave-jacoby/perl/ch-2.pl
new file mode 100644
index 0000000000..f229c6b940
--- /dev/null
+++ b/challenge-162/dave-jacoby/perl/ch-2.pl
@@ -0,0 +1,131 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+use experimental qw{ say postderef signatures state };
+
+use JSON;
+my $json = JSON->new->canonical;
+
+my @tests;
+push @tests,
+ [
+ 'playfair example',
+ 'hide the gold in the tree stump',
+ 'bmodzbxdnabekudmuixmmouvif'
+ ];
+push @tests,
+ [ 'perl and raku', 'the weekly challenge', 'siderwrdulfipaarkcrw' ];
+
+for my $test (@tests) {
+ my ( $key, $plain, $cypher ) = $test->@*;
+ my @square = make_playfair_square($key);
+ my $c1 = encrypt( $key, $plain );
+ my $p1 = decrypt( $key, $cypher );
+ say join "\n\t", $key, $plain, $c1, $cypher, $p1,
+ $cypher eq $c1 ? 'true' : 'false';
+ say '';
+}
+exit;
+
+sub encrypt ( $key, $plaintext ) {
+ my @square = make_playfair_square($key);
+ my @input = make_digrams($plaintext);
+ my @output;
+ for my $digram (@input) {
+ my ( $m, $n ) = split //, $digram;
+ my ( $mx, $my ) = find_position( $m, @square );
+ my ( $nx, $ny ) = find_position( $n, @square );
+ if (0) { 'NO-OP' }
+ elsif ( $mx == $nx ) {
+ my $mm = $square[$mx][ ( $my + 1 ) % 5 ];
+ my $nn = $square[$nx][ ( $ny + 1 ) % 5 ];
+ push @output, $mm . $nn;
+ }
+ elsif ( $my == $ny ) {
+ my $mm = $square[ ( $mx + 1 ) % 5 ][$my];
+ my $nn = $square[ ( $nx + 1 ) % 5 ][$ny];
+ push @output, $mm . $nn;
+ }
+ else {
+ my $mm = $square[$mx][$ny];
+ my $nn = $square[$nx][$my];
+ push @output, $mm . $nn;
+ }
+ }
+ my $zed = '';
+ return lc join '', @output;
+}
+
+sub decrypt ( $key, $cyphertext ) {
+ my @square = make_playfair_square($key);
+ my @input = make_digrams($cyphertext);
+ my @output;
+ for my $digram (@input) {
+ my ( $m, $n ) = split //, $digram;
+ my ( $mx, $my ) = find_position( $m, @square );
+ my ( $nx, $ny ) = find_position( $n, @square );
+ if (0) { 'NO-OP' }
+ elsif ( $mx == $nx ) {
+ my $mm = $square[$mx][ ( $my + 4 ) % 5 ];
+ my $nn = $square[$nx][ ( $ny + 4 ) % 5 ];
+ push @output, $mm . $nn;
+ }
+ elsif ( $my == $ny ) {
+ my $mm = $square[ ( $mx + 4 ) % 5 ][$my];
+ my $nn = $square[ ( $nx + 4 ) % 5 ][$ny];
+ push @output, $mm . $nn;
+ }
+ else {
+ my $mm = $square[$mx][$ny];
+ my $nn = $square[$nx][$my];
+ push @output, $mm . $nn;
+ }
+ }
+ my $zed = '';
+ return lc join '', @output;
+}
+
+sub make_playfair_square( $key ) {
+ my %h;
+ my @array = grep { !$h{$_}++ } grep { /\w/ } ( split //, lc $key ),
+ 'a' .. 'i', 'k' .. 'z';
+ @array = @array[ 0 .. 24 ];
+ my @square;
+ for my $i ( 0 .. 24 ) {
+ my $x = $i % 5;
+ my $y = int $i / 5;
+ $square[$y][$x] = uc $array[$i];
+ }
+ return @square;
+}
+
+sub make_digrams ( $text ) {
+ my @digrams;
+ my $pt = $text;
+ $pt =~ s/[jJ]/i/gmix;
+ $pt =~ s/[^A-Za-z]+//gmix;
+ while ($pt) {
+ my $digram = substr( $pt, 0, 2 );
+ if ( substr( $digram, 0, 1 ) eq substr( $digram, 1, 1, ) ) {
+ $digram = substr( $pt, 0, 1 ) . 'X';
+ substr( $pt, 0, 1 ) = '';
+ }
+ else { substr( $pt, 0, 2 ) = ''; }
+ $digram .= 'X' unless length $digram == 2;
+ push @digrams, uc $digram;
+ }
+ return @digrams;
+}
+
+sub find_position ( $letter, @square ) {
+ exit unless $letter =~ /[A-Z]/mix;
+ $letter = uc $letter;
+ for my $x ( 0 .. 4 ) {
+ for my $y ( 0 .. 4 ) {
+ my $s = $square[$x][$y] || '-';
+ return ( $x, $y ) if $letter eq $s;
+ }
+ }
+ return ( -1, -1 );
+}
diff --git a/challenge-162/julien-fiegehenn/perl/ch-1.pl b/challenge-162/julien-fiegehenn/perl/ch-1.pl
new file mode 100644
index 0000000000..615f3f75c2
--- /dev/null
+++ b/challenge-162/julien-fiegehenn/perl/ch-1.pl
@@ -0,0 +1,46 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use feature 'say';
+use List::Util 'sum';
+
+# Write a script to generate the check digit of given ISBN-13 code. Please refer wikipedia for more information.
+
+# Example
+# ISBN-13 check digit for '978-0-306-40615-7' is 7.
+
+# https://en.wikipedia.org/wiki/ISBN#ISBN-13_check_digit_calculation
+
+sub isbn_13 {
+ my $number = shift;
+
+ die 'Input required' unless $number;
+
+ # clean up the number
+ $number =~ s/\D//g;
+
+ # we need to do maths on each digit
+ my @digits = split //, $number;
+
+ # discard the check digit
+ pop @digits if @digits == 13;
+
+ # do we have the right amount of digits?
+ die 'This does not look like an ISBN-13' unless @digits == 12;
+
+ # tripple all the even digits
+ $_ *= 3 for @digits[1, 3, 5, 7, 9, 11];
+
+ # and do the maths
+ return 10 - sum(@digits) % 10;
+}
+
+say isbn_13(shift);
+
+__END__
+use Test::More;
+
+is isbn_13('978-0-306-40615-7'), 7;
+
+done_testing; \ No newline at end of file
diff --git a/challenge-162/julien-fiegehenn/perl/ch-2.pl b/challenge-162/julien-fiegehenn/perl/ch-2.pl
new file mode 100644
index 0000000000..ee3dc3206f
--- /dev/null
+++ b/challenge-162/julien-fiegehenn/perl/ch-2.pl
@@ -0,0 +1,199 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+use feature 'say';
+
+use constant {ROW => 0, COL => 1};
+
+# Implement encryption and decryption using the Wheatstone-Playfair cipher.
+#
+# Examples:
+# (These combine I and J, and use X as padding.)
+#
+# encrypt("playfair example", "hide the gold in the tree stump") = "bmodzbxdnabekudmuixmmouvif"
+#
+# decrypt("perl and raku", "siderwrdulfipaarkcrw") = "thewexeklychallengex"
+
+# Comments based on example in https://de.wikipedia.org/wiki/Playfair.
+
+# Turn on debugging with the DEBUG=0 environment variable.
+
+say encrypt('playfaire example', 'hide the gold in the tree stump');
+say decrypt("perl and raku", "siderwrdulfipaarkcrw");
+
+sub debug($) {
+ print @_ if $ENV{DEBUG};
+}
+
+sub generate_table {
+ my $key = shift;
+
+ my @letters = grep /[A-IK-Z]/, split //, uc $key;
+ push @letters, 'A' .. 'I', 'K' .. 'Z';
+
+ my ($table, $seen);
+
+ for my $row (0 .. 4) {
+ for my $col (0 .. 4) {
+ while (@letters) {
+ my $letter = shift @letters;
+
+ # skip the ones we've seen
+ redo if $seen->{$letter};
+
+ $table->[$row]->[$col] = $letter;
+ $seen->{$letter} = [$row, $col];
+ last;
+ }
+ debug "$table->[$row]->[$col] ";
+ }
+ debug "\n";
+ }
+ debug "\n";
+
+ return ($table, $seen);
+}
+
+sub encrypt {
+ my ($key, $string) = @_;
+
+ my ($table, $lookup) = generate_table($key);
+
+ my $encrypted = q{};
+
+ my @letters = grep /[A-Z]/, split //, uc $string;
+ while (my ($first, $second) = splice @letters, 0, 2) {
+
+ # pad to create a pair if we only have one letter left
+ $second ||= 'X';
+
+ # handle repeated letters
+ if ($first eq $second) {
+ unshift @letters, $second;
+ $second = 'X';
+ }
+
+ debug "$first$second ";
+
+ # 1. The pair HI forms a rectangle, replace it with BM
+ if ( $lookup->{$first}->[ROW] != $lookup->{$second}->[ROW]
+ && $lookup->{$first}->[COL] != $lookup->{$second}->[COL])
+ {
+ ($first, $second) = (
+ $table->[$lookup->{$first}->[ROW]]->[$lookup->{$second}->[COL]],
+ $table->[$lookup->{$second}->[ROW]]->[$lookup->{$first}->[COL]],
+ );
+ }
+
+ # 2. The pair DE is in a column, replace it with OD
+ elsif ($lookup->{$first}->[ROW] != $lookup->{$second}->[ROW]
+ && $lookup->{$first}->[COL] == $lookup->{$second}->[COL])
+ {
+ ($first, $second) = (
+ $table->[wrap_number($lookup->{$first}->[ROW] + 1)]
+ ->[$lookup->{$first}->[COL]],
+ $table->[wrap_number($lookup->{$second}->[ROW] + 1)]
+ ->[$lookup->{$second}->[COL]],
+ );
+ }
+
+ # 10. The pair EX (X inserted to split EE) is in a row, replace it with XM
+ elsif ($lookup->{$first}->[ROW] == $lookup->{$second}->[ROW]
+ && $lookup->{$first}->[COL] != $lookup->{$second}->[COL])
+ {
+ ($first, $second) = (
+ $table->[$lookup->{$first}->[ROW]]
+ ->[wrap_number($lookup->{$first}->[COL] + 1)],
+ $table->[$lookup->{$second}->[ROW]]
+ ->[wrap_number($lookup->{$second}->[COL] + 1)],
+ );
+ }
+ debug " -> $first$second\n";
+
+ $encrypted .= $first . $second;
+ }
+ debug "\n";
+
+ return $encrypted;
+}
+
+sub decrypt {
+ my ($key, $string) = @_;
+
+ my ($table, $lookup) = generate_table($key);
+
+ my $encrypted = q{};
+
+ my @letters = grep /[A-Z]/, split //, uc $string;
+ while (my ($first, $second) = splice @letters, 0, 2) {
+
+ # pad to create a pair if we only have one letter left
+ $second ||= 'X';
+
+ # handle repeated letters
+ if ($first eq $second) {
+ unshift @letters, $second;
+ $second = 'X';
+ }
+
+ debug "$first$second ";
+
+ # 1. The pair HI forms a rectangle, replace it with BM
+ if ( $lookup->{$first}->[ROW] != $lookup->{$second}->[ROW]
+ && $lookup->{$first}->[COL] != $lookup->{$second}->[COL])
+ {
+ ($first, $second) = (
+ $table->[$lookup->{$first}->[ROW]]->[$lookup->{$second}->[COL]],
+ $table->[$lookup->{$second}->[ROW]]->[$lookup->{$first}->[COL]],
+ );
+ }
+
+ # 2. The pair DE is in a column, replace it with OD
+ elsif ($lookup->{$first}->[ROW] != $lookup->{$second}->[ROW]
+ && $lookup->{$first}->[COL] == $lookup->{$second}->[COL])
+ {
+ ($first, $second) = (
+ $table->[wrap_number($lookup->{$first}->[ROW] - 1)]
+ ->[$lookup->{$first}->[COL]],
+ $table->[wrap_number($lookup->{$second}->[ROW] - 1)]
+ ->[$lookup->{$second}->[COL]],
+ );
+ }
+
+ # 10. The pair EX (X inserted to split EE) is in a row, replace it with XM
+ elsif ($lookup->{$first}->[ROW] == $lookup->{$second}->[ROW]
+ && $lookup->{$first}->[COL] != $lookup->{$second}->[COL])
+ {
+ ($first, $second) = (
+ $table->[$lookup->{$first}->[ROW]]
+ ->[wrap_number($lookup->{$first}->[COL] - 1)],
+ $table->[$lookup->{$second}->[ROW]]
+ ->[wrap_number($lookup->{$second}->[COL] - 1)],
+ );
+ }
+ debug " -> $first$second\n";
+
+ $encrypted .= $first . $second;
+ }
+ debug "\n";
+
+ return $encrypted;
+}
+
+sub wrap_number {
+ my $number = shift;
+
+ return 4 - $number if $number > 4;
+ return $number;
+}
+
+__END__
+
+use Test::More;
+
+is lc encrypt("playfair example", "hide the gold in the tree stump"),
+ "bmodzbxdnabekudmuixmmouvif";
+is lc decrypt("perl and raku", "siderwrdulfipaarkcrw"), "thewexeklychallengex";
+
+done_testing; \ No newline at end of file
diff --git a/challenge-162/luca-ferrari/raku/ch-1.p6 b/challenge-162/luca-ferrari/raku/ch-1.p6
new file mode 100755
index 0000000000..0c4ccef759
--- /dev/null
+++ b/challenge-162/luca-ferrari/raku/ch-1.p6
@@ -0,0 +1,6 @@
+#!raku
+
+sub MAIN( Str $isbn where { $isbn.chars == 12 && $isbn.comb.grep( * ~~ / <[0 .. 9]> / ).elems == $isbn.chars } ) {
+ my $position = 0;
+ say 10 - ( $isbn.comb.map( { $_ * ( ++$position %% 2 ?? 3 !! 1 ) } ).sum % 10 );
+}
diff --git a/challenge-162/luca-ferrari/raku/ch-2.p6 b/challenge-162/luca-ferrari/raku/ch-2.p6
new file mode 100755
index 0000000000..d3e3e6e2fe
--- /dev/null
+++ b/challenge-162/luca-ferrari/raku/ch-2.p6
@@ -0,0 +1,96 @@
+#!raku
+
+sub build-grid( Str $passprhase ) {
+ my @grid;
+ my $counter = 0;
+ for $passprhase.comb {
+ # skip existing letters
+ next if @grid.grep( $_ );
+ next if $_ !~~ / <[ a .. z ]> /;
+
+ # insert this letter
+ @grid.push: $_;
+ @grid.push: '|' if ++$counter %% 5;
+ }
+
+ # add the other letters
+ unless ( @grid.grep( '|' ).elems == 5 ) {
+ for 'a' .. 'z' {
+ next if @grid.grep( $_ );
+ next if $_ ~~ / i /;
+ next if $_ ~~ / j /;
+
+ # insert this letter
+ @grid.push: $_;
+ @grid.push: '|' if ++$counter %% 5;
+ last if @grid.grep( '|' ).elems == 5;
+ }
+ }
+
+ # now split the array into a matrix
+ my @matrix;
+ for @grid.join.split( '|' ) {
+ next if ! $_;
+ @matrix.push: [ $_.comb ];
+ }
+
+ say @matrix;
+ return @matrix;
+}
+
+
+sub build-pairs( Str $needle ) {
+
+ my @mangled;
+ my @current;
+ for $needle.comb {
+ next if $_ ~~ / ' ' /;
+
+ @current.push: $_ if ! @mangled.grep( $_ );
+ @current.push: 'X' if @mangled.grep( $_ );
+
+ if @current.elems == 2 {
+ @mangled.push: [@current];
+ @current = ();
+ }
+ }
+
+ return @mangled;
+}
+
+
+sub MAIN() {
+ my @key-matrix = build-grid( 'playfair example' );
+ my @pairs = build-pairs( 'hide the gold in the tree stump' );
+
+
+ for @pairs -> @current-pair {
+ my @rectangle;
+
+ for 0 ..^ @current-pair {
+ my $current_letter = @current-pair[ $_ ];
+ my $found = False;
+
+ for 0 ..^ @key-matrix.elems -> $row {
+ for 0 ..^ 5 -> $column {
+ if @key-matrix[ $row ][ $column ] ~~ $current_letter {
+ # found!
+ @rectangle.push: ( row => $row, col => $column ).Hash;
+ $found = True;
+ }
+
+ last if $found;
+ }
+
+ last if $found;
+ }
+ }
+
+ say @current-pair.join;
+ say @rectangle;
+
+ say @rectangle[ 0 ].^name;
+# my $is-rectangle = @rectangle[ 0 ]{ row } != @rectangle[ 1 ]{ row } && @rectangle[ 0 ]{ col } != @rectangle[ 1 ]{ col };
+# say "rettangolo $is-rectangle";
+ }
+}
diff --git a/challenge-162/peter-campbell-smith/blog.txt b/challenge-162/peter-campbell-smith/blog.txt
new file mode 100644
index 0000000000..c35d02e319
--- /dev/null
+++ b/challenge-162/peter-campbell-smith/blog.txt
@@ -0,0 +1 @@
+https://pjcs-pwc.blogspot.com/2022/04/checksums-and-early-encryption.html
diff --git a/challenge-162/peter-campbell-smith/perl/ch-1.pl b/challenge-162/peter-campbell-smith/perl/ch-1.pl
new file mode 100755
index 0000000000..4462e8d091
--- /dev/null
+++ b/challenge-162/peter-campbell-smith/perl/ch-1.pl
@@ -0,0 +1,34 @@
+#!/usr/bin/perl
+
+# Peter Campbell Smith - 2022-04-25
+# PWC 162 task 1
+
+use v5.28;
+use strict;
+use warnings;
+use utf8;
+
+# Write a script to generate the check digit of given ISBN-13 code.
+
+my ($sum, $test, @digits, @multipliers, @tests);
+
+# data
+@tests = ('978-0-306-40615-7', '978-1-85345-445-5', '978-3-468-98143-2');
+
+# multipliers of successive digits as defined
+@multipliers = qw(1 3 1 3 1 3 1 3 1 3 1 3);
+
+for $test (@tests) {
+
+ # eliminate non-digits
+ @digits = ();
+ push @digits, $1 while $test =~ m|(\d)|g;
+
+ # create weighted sum of first 12 digits
+ $sum = 0;
+ $sum += $digits[$_] * $multipliers[$_] for (0 .. 11);
+
+ # and the 13th digit is 10 minus the sum, mod 10
+ say qq[ISBN-13 check digit for '$test' is ] . (10 - $sum % 10) . '.';
+}
+
diff --git a/challenge-162/peter-campbell-smith/perl/ch-2.pl b/challenge-162/peter-campbell-smith/perl/ch-2.pl
new file mode 100755
index 0000000000..990cb22b44
--- /dev/null
+++ b/challenge-162/peter-campbell-smith/perl/ch-2.pl
@@ -0,0 +1,133 @@
+#!/usr/bin/perl
+
+# Peter Campbell Smith - 2022-04-25
+# PWC 162 task 2
+
+use v5.28;
+use strict;
+use warnings;
+use utf8;
+
+my ($c, $j, $key, $letter, $matrix, $r, %used, @key, @letters, @plain,
+ $plain, $fixed, $prev, %locate, $encrypted, $decrypted);
+
+# Implement encryption and decryption using the Wheatstone-Playfair cipher.
+
+# data
+$key[0] = 'playfair example';
+$plain[0] = 'hide the gold in the tree stump';
+
+$key[1] = 'Perl and Raku';
+$plain[1] = 'The Weekly Challenge';
+
+$key[2] = 'the quick brown fox jumps over the lazy dog';
+$plain[2] = q[The curfew tolls the knell of parting day, the lowing herd winds slowly o'er the lea];
+
+# loop over key/plaintext pairs
+for ($j = 0; $key[$j]; $j ++) {
+
+ # create matrix
+ say qq[\nPlaintext: $plain[$j]\nKey: $key[$j]];
+ $key = lc($key[$j]);
+ $key =~ s|[^a-z]||g;
+ @letters = split(//, $key);
+
+ # put the unique letters of the key into successive cells of the matrix
+ ($r, $c) = (0, 0);
+ %used = ();
+ for $letter (@letters) {
+ $letter = 'i' if $letter eq 'j';
+ next if $used{$letter}; # seen this letter already
+ $used{$letter} = 1;
+ $$matrix[$r][$c] = $letter;
+ $locate{$letter} = [$r, $c]; # row and column containing $letter
+ $c ++;
+ if ($c == 5) { # reached the end of a row
+ $c = 0;
+ $r ++;
+ }
+ }
+
+ # now add the rest of the alphabet
+ for $letter ('a' .. 'z') {
+ $letter = 'i' if $letter eq 'j';
+ next if $used{$letter};
+ $used{$letter} = 1;
+ $$matrix[$r][$c] = $letter;
+ $locate{$letter} = [$r, $c];
+ $c ++;
+ if ($c == 5) {
+ $c = 0;
+ $r ++;
+ }
+ }
+
+ # show matrix
+ say qq[Matrix:];
+ for $r (0..4) {
+ for $c (0..4) {
+ print $$matrix[$r][$c] . ' ';
+ }
+ say '';
+ }
+
+ # encrypt the plaintext
+ $plain = lc($plain[$j]);
+ $plain =~ s|[^a-z]||g;
+
+ # insert 'x' to split paired letters
+ $fixed = $prev = '';
+ while ($plain =~ m|(.)|g) {
+ $fixed .= 'x' if ($1 eq $prev and length($fixed) % 2 == 1);
+ $fixed .= $1;
+ $prev = $1;
+ }
+
+ # suffix 'x' if text has odd length
+ $fixed .= 'x' if (length($fixed) % 2 == 1);
+
+ # encrypt text 2 letters at a time
+ $encrypted = '';
+ while ($fixed =~ m|(.)(.)|g) {
+ $encrypted .= playfair(1, $1, $2);
+ }
+ say qq[Encrypted: $encrypted];
+
+ # and decrypt it
+ $decrypted = '';
+ while ($encrypted =~ m|(.)(.)|g) {
+ $decrypted .= playfair(0, $1, $2);
+ }
+ say qq[Decrypted: $decrypted];
+}
+
+sub playfair { # (encrypt, letter1, letter2)
+
+ my ($encrypt, $g1, $g2) = @_;
+ my ($g1_row, $g1_col, $g2_row, $g2_col);
+
+ # get the row and column coordinates of each letter
+ ($g1_row, $g1_col) = @{$locate{$g1}};
+ ($g2_row, $g2_col) = @{$locate{$g2}};
+
+ # the letter pair defines a rectangle - swap their columns
+ if ($g1_row != $g2_row && $g1_col != $g2_col) {
+ return $$matrix[$g1_row][$g2_col] . $$matrix[$g2_row][$g1_col];
+
+ # pair in same column - shift down to encrypt, up to decrypt
+ } elsif ($g1_col == $g2_col) {
+ if ($encrypt) {
+ return $$matrix[($g1_row + 1) % 5][$g1_col] . $$matrix[($g2_row + 1) % 5][$g2_col];
+ } else { # decrypt
+ return $$matrix[($g1_row + 4) % 5][$g1_col] . $$matrix[($g2_row + 4) % 5][$g2_col];
+ }
+
+ # pair in same row - shift right to encrypt, left to decrypt
+ } elsif ($g1_row == $g2_row) {
+ if ($encrypt) {
+ return $$matrix[$g1_row][($g1_col + 1) % 5] . $$matrix[$g2_row][($g2_col + 1) % 5];
+ } else { # decrypt
+ return $$matrix[$g1_row,][($g1_col + 4) % 5] . $$matrix[$g2_row][($g2_col + 4) % 5];
+ }
+ }
+}
diff --git a/challenge-162/robert-dicicco/perl/ch-1.pl b/challenge-162/robert-dicicco/perl/ch-1.pl
new file mode 100644
index 0000000000..1cf0ee35fe
--- /dev/null
+++ b/challenge-162/robert-dicicco/perl/ch-1.pl
@@ -0,0 +1,28 @@
+#!perl.exe
+
+use strict;
+use warnings;
+use feature qw/say/;
+
+# AUTHOR: Robert DiCicco
+# DATE: 25-APR-2022
+# Challenge 162 ISBN-13 ( Perl )
+
+sub makeCheckDigit {
+ my $n = shift;
+
+ my @arr = split(//,$n);
+ my $evensum = $arr[0] + $arr[2] + $arr[4] + $arr[6] + $arr[8] + $arr[10];
+ my $oddsum = ($arr[1] + $arr[3] + $arr[5] + $arr[7] + $arr[9] + $arr[11]) * 3;
+ my $presum = ($evensum + $oddsum) % 10;
+ my $checkdigit = 10 - $presum;
+
+ return $checkdigit;
+}
+
+my $isbn = '978-0-306-40615-7';
+my $num = substr($isbn,0,15);
+$num =~ tr/\-//d;
+my $checkdigit = makeCheckDigit($num);
+
+say "ISBN-13 check digit for $isbn is $checkdigit.";
diff --git a/challenge-162/robert-dicicco/raku/ch-1.raku b/challenge-162/robert-dicicco/raku/ch-1.raku
new file mode 100644
index 0000000000..f45b241954
--- /dev/null
+++ b/challenge-162/robert-dicicco/raku/ch-1.raku
@@ -0,0 +1,22 @@
+use v6;
+
+# AUTHOR: Robert DiCicco
+# DATE: 26-APR-2022
+# Challenge 162 ISBN-13 ( Raku )
+
+sub makeCheckDigit ( $n) {
+ my @arr = $n.comb;
+ my $evensum = @arr[0] + @arr[2] + @arr[4] + @arr[6] + @arr[8] + @arr[10];
+ my $oddsum = (@arr[1] + @arr[3] + @arr[5] + @arr[7] + @arr[9] + @arr[11]) * 3;
+ my $presum = ($evensum + $oddsum) % 10;
+ my $checkdigit = 10 - $presum;
+
+ return $checkdigit;
+}
+
+my $isbn = '978-0-306-40615-7';
+my $num = substr($isbn,0,15);
+$num ~~ tr/-//;
+my $checkdigit = makeCheckDigit($num);
+
+say "ISBN-13 check digit for $isbn is $checkdigit.";