aboutsummaryrefslogtreecommitdiff
path: root/challenge-162
diff options
context:
space:
mode:
authorMohammad S Anwar <mohammad.anwar@yahoo.com>2022-05-04 09:55:07 +0100
committerMohammad S Anwar <mohammad.anwar@yahoo.com>2022-05-04 09:55:07 +0100
commit00424daeddd40cc9d98cd1e4111541ddccd0f235 (patch)
treea866f42255bbc2ad91ee28d8b2d16e47a0cef3d2 /challenge-162
parentb13444bb5307ad7c7051ace6031dd063bac3cc32 (diff)
downloadperlweeklychallenge-club-00424daeddd40cc9d98cd1e4111541ddccd0f235.tar.gz
perlweeklychallenge-club-00424daeddd40cc9d98cd1e4111541ddccd0f235.tar.bz2
perlweeklychallenge-club-00424daeddd40cc9d98cd1e4111541ddccd0f235.zip
- Added solutions by Pete Houston.
Diffstat (limited to 'challenge-162')
-rwxr-xr-xchallenge-162/pete-houston/perl/ch-1.pl25
-rwxr-xr-xchallenge-162/pete-houston/perl/ch-2.pl143
2 files changed, 168 insertions, 0 deletions
diff --git a/challenge-162/pete-houston/perl/ch-1.pl b/challenge-162/pete-houston/perl/ch-1.pl
new file mode 100755
index 0000000000..f729bdd1d3
--- /dev/null
+++ b/challenge-162/pete-houston/perl/ch-1.pl
@@ -0,0 +1,25 @@
+#!/usr/bin/env perl
+#===============================================================================
+#
+# FILE: 16201.pl
+#
+# USAGE: ./16201.pl ISBN
+#
+# DESCRIPTION: Calculate the check digit for the given ISBN
+#
+# REQUIREMENTS: List::Util (core)
+# AUTHOR: Pete Houston (pete), cpan@openstrike.co.uk
+# ORGANIZATION: Openstrike
+# VERSION: 1.0
+# CREATED: 25/04/22
+#===============================================================================
+
+use strict;
+use warnings;
+use List::Util qw/sum pairmap/;
+
+my @digits = (my $in = shift) =~ /(\d)/gaa;
+my $sum = sum pairmap { $a + 3 * $b } @digits[0..11];
+my $check = (0 - $sum) % 10;
+
+print "ISBN-13 check digit for '$in' is $check\n";
diff --git a/challenge-162/pete-houston/perl/ch-2.pl b/challenge-162/pete-houston/perl/ch-2.pl
new file mode 100755
index 0000000000..901cb48659
--- /dev/null
+++ b/challenge-162/pete-houston/perl/ch-2.pl
@@ -0,0 +1,143 @@
+#!/usr/bin/env perl
+#===============================================================================
+#
+# FILE: 16202.pl
+#
+# USAGE: ./16202.pl [ -d ] -k KEYSTRING [ -t TEXT | INFILE ]
+#
+# DESCRIPTION: Encrypt/decrypt usng the Wheatstone-Playfair cipher
+#
+# OPTIONS: Use -d to decrypt (default is to encrypt)
+# OPTIONS: Use -t to provide a text string as an argument
+# without -t, use the argument as the filename to read from
+# with no argument at all, read from STDIN
+# REQUIREMENTS: Getopt::Long::Modern
+# AUTHOR: Pete Houston (pete), cpan@openstrike.co.uk
+# ORGANIZATION: Openstrike
+# VERSION: 1.0
+# CREATED: 26/04/22
+#===============================================================================
+
+use strict;
+use warnings;
+
+package ACME::Crypt::Playfair;
+
+sub new {
+ my ($class, $key, $opts) = @_;
+
+ my $self = {
+ key => $key,
+ split_char => $opts->{split_char} // 'x',
+ };
+ bless $self, $class;
+ $self->build;
+ return $self;
+}
+
+sub build {
+ my $self = shift;
+
+ # Normalise the key;
+ my $key = lc $self->{key};
+ $key =~ s/[^a-z]//g;
+
+ my %seen;
+ my $i = 0;
+ my $j = 0;
+ my @grid;
+ my @chars = (split (//, $key), grep { $_ ne 'j' } map { chr } 97 .. 122);
+ for my $c (@chars) {
+ $c = 'i' if $c eq 'j';
+ next if exists $seen{$c};
+ push @grid, $c;
+ $seen{$c} = [ $j, $i ];
+ $i++;
+ $j++, $i = 0 if $i > 4;
+ }
+ {
+ my $kc = scalar keys %seen;
+ die "letter count is $kc! Should be 25.\n" unless $kc == 25;
+ }
+
+ # Construct the 5x5 grid
+ $self->{grid} = [];
+ for my $x (0 .. 4) {
+ $self->{grid}[$x] = [@grid[(5 * $x) .. (5 * $x + 4)]];
+ }
+ $self->{pos} = \%seen;
+ return;
+}
+
+sub encrypt {
+ my ($self, $in) = @_;
+ $self->crypto ($in, 1, [0, 1]);
+}
+
+sub decrypt {
+ my ($self, $in) = @_;
+ $self->crypto ($in, -1, [1, 0]);
+}
+
+sub crypto {
+ my ($self, $in, $dir, $order) = @_;
+
+ my $out = '';
+ $in = lc $in;
+ $in =~ tr /a-z//cd;
+ $in =~ tr/j/i/;
+ while (length $in) {
+ my $buf = substr $in, 0, 2, '';
+ my @bc = split //, $buf;
+ $bc[1] //= $self->{split_char};
+ if ($bc[0] eq $bc[1]) {
+ $in = $bc[1] . $in;
+ $bc[1] = $self->{split_char};
+ }
+
+ if ($self->{pos}{$bc[0]}[0] == $self->{pos}{$bc[1]}[0]) {
+ # Same row
+ my $r = $self->{grid}[$self->{pos}{$bc[0]}[0]];
+ $bc[$_] = $r->[($self->{pos}{$bc[$_]}[1] + $dir) % 5] for 0, 1;
+ } elsif ($self->{pos}{$bc[0]}[1] == $self->{pos}{$bc[1]}[1]) {
+ # Same col
+ my $cn = $self->{pos}{$bc[0]}[1];
+ $bc[$_] = $self->{grid}[($self->{pos}{$bc[$_]}[0] + $dir) % 5][$cn]
+ for 0, 1;
+ } else {
+ # Copy the old one to avoid clobbering
+ my @obc = @bc;
+ $bc[$_] = $self->{grid}[
+ $self->{pos}{$obc[$_] }[0]]
+ [$self->{pos}{$obc[1 - $_]}[1]] for @$order;
+ }
+ $out .= $bc[0] . $bc[1];
+ }
+ return $out;
+}
+
+################################################################################
+
+package main;
+
+use Getopt::Long::Modern;
+
+GetOptions (
+ 'd|decrypt' => \my $decrypt,
+ 'k|key=s' => \my $key,
+ 't|text=s' => \my $text
+);
+
+my $action = defined ($decrypt) ? 'decrypt' : 'encrypt';
+unless (defined $text) {
+ my $fh = \*STDIN;
+ if (defined $_[0]) {
+ open $fh, '<', $_[0] or die "Cannot open $_[0]: $!";
+ }
+ local $/ = undef;
+ $text = <$fh>;
+}
+
+my $engine = ACME::Crypt::Playfair->new ($key);
+my $output = $engine->$action ($text);
+print "$output\n";