diff options
| author | Rick Bychowski <rick@hiranyaloka.com> | 2022-05-01 02:23:01 -0700 |
|---|---|---|
| committer | Rick Bychowski <rick@hiranyaloka.com> | 2022-05-01 02:23:01 -0700 |
| commit | 8920b32abbf19d0f08e41992b01dcb9e7670d484 (patch) | |
| tree | b939d24f62d11e410495c3c87c4078dd11e1829a /challenge-162 | |
| parent | 0799d0abf2f140e508f5ba8fbfcb47ce64313056 (diff) | |
| download | perlweeklychallenge-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-x | challenge-162/rick-bychowski/raku/ch-1.raku | 30 | ||||
| -rwxr-xr-x | challenge-162/rick-bychowski/raku/ch-2.raku | 51 |
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'"; +} |
