aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
3 files changed, 168 insertions, 0 deletions
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];
+ }
+ }
+}