diff options
| author | Mohammad S Anwar <mohammad.anwar@yahoo.com> | 2022-05-04 09:55:07 +0100 |
|---|---|---|
| committer | Mohammad S Anwar <mohammad.anwar@yahoo.com> | 2022-05-04 09:55:07 +0100 |
| commit | 00424daeddd40cc9d98cd1e4111541ddccd0f235 (patch) | |
| tree | a866f42255bbc2ad91ee28d8b2d16e47a0cef3d2 /challenge-162 | |
| parent | b13444bb5307ad7c7051ace6031dd063bac3cc32 (diff) | |
| download | perlweeklychallenge-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-x | challenge-162/pete-houston/perl/ch-1.pl | 25 | ||||
| -rwxr-xr-x | challenge-162/pete-houston/perl/ch-2.pl | 143 |
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"; |
