aboutsummaryrefslogtreecommitdiff
path: root/challenge-162
diff options
context:
space:
mode:
authorRick Bychowski <rick@hiranyaloka.com>2022-05-01 02:23:01 -0700
committerRick Bychowski <rick@hiranyaloka.com>2022-05-01 02:23:01 -0700
commit8920b32abbf19d0f08e41992b01dcb9e7670d484 (patch)
treeb939d24f62d11e410495c3c87c4078dd11e1829a /challenge-162
parent0799d0abf2f140e508f5ba8fbfcb47ce64313056 (diff)
downloadperlweeklychallenge-club-8920b32abbf19d0f08e41992b01dcb9e7670d484.tar.gz
perlweeklychallenge-club-8920b32abbf19d0f08e41992b01dcb9e7670d484.tar.bz2
perlweeklychallenge-club-8920b32abbf19d0f08e41992b01dcb9e7670d484.zip
ch-162 ISBN-13 Playfair cipher
Diffstat (limited to 'challenge-162')
-rwxr-xr-xchallenge-162/rick-bychowski/raku/ch-1.raku30
-rwxr-xr-xchallenge-162/rick-bychowski/raku/ch-2.raku51
2 files changed, 81 insertions, 0 deletions
diff --git a/challenge-162/rick-bychowski/raku/ch-1.raku b/challenge-162/rick-bychowski/raku/ch-1.raku
new file mode 100755
index 0000000000..6c2ba2a909
--- /dev/null
+++ b/challenge-162/rick-bychowski/raku/ch-1.raku
@@ -0,0 +1,30 @@
+#!/usr/bin/env raku
+# https://theweeklychallenge.org/blog/perl-weekly-challenge-162/
+# https://en.wikipedia.org/wiki/ISBN
+
+sub MAIN( Str $isbn ) {
+ my @digits = $isbn.trans( (/<[ \s \- ]>/ => '') ).comb;
+ given @digits.elems {
+ when 13 {
+ my $digit-to-check = @digits.pop;
+ my $checkdigit = checksum(@digits);
+ if $digit-to-check == $checkdigit {
+ say "Your checkdigit '$digit-to-check'",
+ " matches our calculated digit '$checkdigit'";
+ } else {
+ say "Your checkdigit '$digit-to-check'",
+ " does NOT match our calculated digit '$checkdigit'";
+ }
+ }
+ when 12 {
+ my $checkdigit = checksum(@digits);
+ say "Your checkdigit is '$checkdigit'";
+ }
+ default { say "Not a valid ISBN: '$isbn'" };
+ }
+}
+
+sub checksum( @digits where {(.all ~~ /^\d$/) and (@digits.elems == 12 )}) {
+ my $checkdigit = (@digits Z* <1 3 1 3 1 3 1 3 1 3 1 3>).sum mod 10;
+ return $checkdigit == 0 ?? 0 !! 10 - $checkdigit;
+}
diff --git a/challenge-162/rick-bychowski/raku/ch-2.raku b/challenge-162/rick-bychowski/raku/ch-2.raku
new file mode 100755
index 0000000000..24b9948f95
--- /dev/null
+++ b/challenge-162/rick-bychowski/raku/ch-2.raku
@@ -0,0 +1,51 @@
+#!/usr/bin/env raku
+# https://theweeklychallenge.org/blog/perl-weekly-challenge-162/
+# https://en.wikipedia.org/wiki/Playfair_cipher
+
+sub MAIN(
+ Str $cmd where {$cmd ~~ /^'encrypt'|'decrypt'$/} = 'encrypt',
+ Str :$key = 'Playfair Example', # can contain non-alpha chars
+ Str :$secret = 'Meet me at the Whisky a Go Go', # the text to encrypt or decrypt
+ Str :$ij where {$ij.chars > 1} = 'ij', # the two redundant chars, keep first
+ Str :$xq where {$xq.chars > 1} = 'xq' # padding for double letter or odd secret
+) {
+ my $i = $ij.comb[0];
+ my $j = $ij.comb[1];
+ # combine key and alphabet, remove non-alpha, replace i/j
+ my $matrix = ($key ~ ('a' .. 'z').join).lc.subst(/<-[a .. z]>/,'', :g).subst(/$j/,$i, :g);
+ my @matrix = $matrix.comb.unique.map: -> $a,$b,$c,$d,$e {[$a,$b,$c,$d,$e]};
+ my %matrix; # HoA: keys are letters, values are matrix indices
+ loop ( my $m=0; $m < 5; $m++ ) {
+ loop ( my $n=0; $n < 5; $n++ ){
+ %matrix{"@matrix[$m][$n]"} = [$m,$n];
+ }
+ }
+ my @result;
+ my $plaintext = $secret.lc.subst(/<-[a .. z]>/,'', :g).subst(/$j/,$i, :g);
+ $plaintext = $plaintext.chars % 2 == 1 ?? $plaintext ~ $xq.comb.[0] !! $plaintext;
+ for $plaintext.comb -> $a, $beta {
+ my $b = $beta; # make copy in case it needs to be substituted
+ $b = $a eq $beta ?? $xq.comb.[0] !! $beta; # try subs to 'x'
+ $b = $a eq $b ?? $xq.comb.[1] !! $beta; # 'x' fails, subs to 'q'
+ my $am = %matrix{$a}[0];
+ my $an = %matrix{$a}[1];
+ my $bm = %matrix{$b}[0];
+ my $bn = %matrix{$b}[1];
+ if $am == $bm { # same row
+ @result.push(@matrix[$am][($an + 1) % 5]) if $cmd eq 'encrypt';
+ @result.push(@matrix[$bm][($bn + 1) % 5]) if $cmd eq 'encrypt';
+ @result.push(@matrix[$am][($an - 1) % 5]) if $cmd eq 'decrypt';
+ @result.push(@matrix[$bm][($bn - 1) % 5]) if $cmd eq 'decrypt';
+ } elsif $an == $bn { # same column
+ @result.push(@matrix[($am + 1) % 5][$an]) if $cmd eq 'encrypt';
+ @result.push(@matrix[($bm + 1) % 5][$bn]) if $cmd eq 'encrypt';
+ @result.push(@matrix[($am - 1) % 5][$an]) if $cmd eq 'decrypt';
+ @result.push(@matrix[($bm - 1) % 5][$bn]) if $cmd eq 'decrypt';
+ } else { # different row and column
+ @result.push(@matrix[$am][$bn]);
+ @result.push(@matrix[$bm][$an]);
+ }
+ }
+ my $result = @result.join('');
+ say "'$result'";
+}