diff options
| author | Mohammad S Anwar <Mohammad.Anwar@yahoo.com> | 2022-05-02 00:38:09 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-05-02 00:38:09 +0100 |
| commit | d51db3e52a7b29c245245e427d96237ba29237a2 (patch) | |
| tree | ae2729324a7eea6b3960b1e961c5bf11b8a5caa5 /challenge-162 | |
| parent | f677098515ea60add06ee12993635f9a7b974a7b (diff) | |
| parent | 10d7f4ae073e07c0e18bf29cc07f310240bda2a2 (diff) | |
| download | perlweeklychallenge-club-d51db3e52a7b29c245245e427d96237ba29237a2.tar.gz perlweeklychallenge-club-d51db3e52a7b29c245245e427d96237ba29237a2.tar.bz2 perlweeklychallenge-club-d51db3e52a7b29c245245e427d96237ba29237a2.zip | |
Merge pull request #6038 from dcw803/master
imported my solutions to this week's 2 tasks
Diffstat (limited to 'challenge-162')
| -rw-r--r-- | challenge-162/duncan-c-white/C/.build | 2 | ||||
| -rw-r--r-- | challenge-162/duncan-c-white/C/Makefile | 13 | ||||
| -rw-r--r-- | challenge-162/duncan-c-white/C/README | 3 | ||||
| -rw-r--r-- | challenge-162/duncan-c-white/C/ch-1.c | 99 | ||||
| -rw-r--r-- | challenge-162/duncan-c-white/README | 57 | ||||
| -rwxr-xr-x | challenge-162/duncan-c-white/perl/ch-1.pl | 54 | ||||
| -rwxr-xr-x | challenge-162/duncan-c-white/perl/ch-2.pl | 181 |
7 files changed, 373 insertions, 36 deletions
diff --git a/challenge-162/duncan-c-white/C/.build b/challenge-162/duncan-c-white/C/.build new file mode 100644 index 0000000000..7a8295430e --- /dev/null +++ b/challenge-162/duncan-c-white/C/.build @@ -0,0 +1,2 @@ +BUILD = ch-1 +#CFLAGS = -g diff --git a/challenge-162/duncan-c-white/C/Makefile b/challenge-162/duncan-c-white/C/Makefile new file mode 100644 index 0000000000..61dae2a678 --- /dev/null +++ b/challenge-162/duncan-c-white/C/Makefile @@ -0,0 +1,13 @@ +BUILD = ch-1 +CC = gcc +CFLAGS = #-g + +all: $(BUILD) + +clean: + /bin/rm -f $(BUILD) *.o core a.out + +ch-1: ch-1.o + $(CC) $(CFLAGS) ch-1.o -o ch-1 + +ch-1.o: ch-1.c diff --git a/challenge-162/duncan-c-white/C/README b/challenge-162/duncan-c-white/C/README new file mode 100644 index 0000000000..61d52a58c0 --- /dev/null +++ b/challenge-162/duncan-c-white/C/README @@ -0,0 +1,3 @@ +Thought I'd also have a go at translating ch-1.pl into C.. + +Produces identical (non-debugging) output to my ch-1.pl:-) diff --git a/challenge-162/duncan-c-white/C/ch-1.c b/challenge-162/duncan-c-white/C/ch-1.c new file mode 100644 index 0000000000..c263422dbf --- /dev/null +++ b/challenge-162/duncan-c-white/C/ch-1.c @@ -0,0 +1,99 @@ +/* + * TASK #1 - ISBN-13 + * + * Write a script to generate the check digit of given ISBN-13 code. Please + * refer to + * + * https://en.wikipedia.org/wiki/ISBN#ISBN-13_check_digit_calculation + * + * for more information. In summary, take each of the first 12 digits of + * an ISBN code, from left to right, multiple 1st, 3rd, 5th etc by 1, and + * the 2nd, 4th, 6th etc by 3, sum the result. Mod 10 the sum. Subtract + * the sum from 10. Mod 10 the result. + * + * Example + * + * ISBN-13 check digit for '978-0-306-40615-7' is 7. + * + * MY NOTES: ok. Pretty easy. + * + * GUEST LANGUAGE: THIS IS THE C VERSION. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <stdbool.h> +#include <string.h> +#include <assert.h> +#include <unistd.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + + + + +bool debug=false; + + +int main( int argc, char **argv ) +{ + if( argc != 2 ) + { + fprintf( stderr, "Usage: isbn-13 isbn-number\n" ); + exit(1); + } + char *input = argv[1]; + char isbn[14]; + + // copy input to isbn, omitting the dashes + char *dst = isbn; + char *src = input; + while( *src ) + { + if( *src != '-' ) + { + *dst++ = *src; + } + src++; + } + if( debug ) + { + printf( "debug: isbn w/o dashes = %s\n", isbn ); + } + + // chop off the last digit if len==13, check length + int len = strlen(isbn); + if( len==13 ) + { + isbn[12] = '\0'; + len--; + } + if( debug ) + { + printf( "debug: isbn w/o checkdigit = %s\n", isbn ); + } + if( len != 12 ) + { + fprintf( stderr, + "isbn-checker: length of %s (should be 12) is %d\n", + isbn, len ); + exit(1); + } + + int scale = 3; + int total = 0; + for( src = isbn; *src; src++ ) + { + scale = 4-scale; + total += scale * (*src-'0'); + } + total %= 10; + total = 10-total; + total %= 10; + + printf( "%d\n", total ); + + return 0; +} diff --git a/challenge-162/duncan-c-white/README b/challenge-162/duncan-c-white/README index a10c12ba95..4b5c1a964f 100644 --- a/challenge-162/duncan-c-white/README +++ b/challenge-162/duncan-c-white/README @@ -1,52 +1,37 @@ -TASK #1 - Abecedarian Words +TASK #1 - ISBN-13 -An abecedarian word is a word whose letters are arranged in alphabetical -order. For example, 'knotty' is an abecedarian word, but 'knots' -is not. Output or return a list of all abecedarian words in the -dictionary, sorted in decreasing order of length. +Write a script to generate the check digit of given ISBN-13 code. Please +refer to -Optionally, using only abecedarian words, leave a short comment in your code to make your reviewer smile. - -MY NOTES: ok. Pretty easy. - -GUEST LANGUAGE: As a bonus, I also had a go at translating ch-1.pl into C, -look in the C directory for that. +https://en.wikipedia.org/wiki/ISBN#ISBN-13_check_digit_calculation +for more information. In summary, take each of the first 12 digits of +an ISBN code, from left to right, multiple 1st, 3rd, 5th etc by 1, and +the 2nd, 4th, 6th etc by 3, sum the result. Mod 10 the sum. Subtract +the sum from 10. Mod 10 the result. -TASK #2 - Pangrams +Example -A pangram is a sentence or phrase that uses every letter in the English -alphabet at least once. For example, perhaps the most well known -pangram is: +ISBN-13 check digit for '978-0-306-40615-7' is 7. -the quick brown fox jumps over the lazy dog - -Using the provided dictionary, so that you don't need to include -individual copy, generate at least one pangram. +MY NOTES: ok. Pretty easy. -Your pangram does not have to be a syntactically valid English sentence -(doing so would require far more work, and a dictionary of nouns, verbs, -adjectives, adverbs, and conjunctions). Also note that repeated letters, -and even repeated words, are permitted. +GUEST LANGUAGE: As a bonus, I also had a go at translating ch-1.pl into C, +look in the C directory for that. -BONUS: Constrain or optimize for something interesting (completely up -to you), such as: -Shortest possible pangram (difficult) +TASK #2 - Wheatstone-Playfair -Pangram which contains only abecedarian words (see challenge 1) +Implement encryption and decryption using the Wheatstone-Playfair cipher: -Pangram such that each word "solves" exactly one new letter. For example, -such a pangram might begin with (newly solved letters in bold): - a ah hi hid die ice tea ... +https://en.wikipedia.org/wiki/Playfair_cipher - (What is the longest possible pangram generated with this method? All - solutions will contain 26 words, so focus on the letter count.) +Examples: -Pangrams that have the weirdest (PG-13) Google image search results +(These combine I and J, and use X as padding.) -Anything interesting goes! +encrypt("playfair example", "hide the gold in the tree stump") = "bmodzbxdnabekudmuixmmouvif" +decrypt("perl and raku", "siderwrdulfipaarkcrw") = "thewexeklychallengex" -MY NOTES: hmmm. Pretty easy to find a pangram in a brute force fashion, -but anything more constrained sounds pretty hard. +MY NOTES: hmmm. Not too hard. diff --git a/challenge-162/duncan-c-white/perl/ch-1.pl b/challenge-162/duncan-c-white/perl/ch-1.pl new file mode 100755 index 0000000000..2bcad8f22a --- /dev/null +++ b/challenge-162/duncan-c-white/perl/ch-1.pl @@ -0,0 +1,54 @@ +#!/usr/bin/perl +# +# TASK #1 - ISBN-13 +# +# Write a script to generate the check digit of given ISBN-13 code. Please +# refer to +# +# https://en.wikipedia.org/wiki/ISBN#ISBN-13_check_digit_calculation +# +# for more information. In summary, take each of the first 12 digits of +# an ISBN code, from left to right, multiple 1st, 3rd, 5th etc by 1, and +# the 2nd, 4th, 6th etc by 3, sum the result. Mod 10 the sum. Subtract +# the sum from 10. Mod 10 the result. +# +# Example +# +# ISBN-13 check digit for '978-0-306-40615-7' is 7. +# +# MY NOTES: ok. Pretty easy. +# +# GUEST LANGUAGE: As a bonus, I also had a go at translating ch-1.pl into C, +# look in the C directory for that. +# + +use strict; +use warnings; +use feature 'say'; +use Getopt::Long; +use Data::Dumper; +use List::Util qw(sum0); + +my $debug=0; +die "Usage: isbn-13-checker [--debug] isbn-number\n" + unless GetOptions( "debug"=>\$debug ) && @ARGV==1; + +my $isbn = shift; +$isbn =~ tr/-//d; +my $len = length($isbn); +if( $len==13 ) +{ + $isbn =~ s/.$//; + $len--; +} + +die "isbn-13 checker: $isbn (len $len) should be 12 chars long\n" + unless $len == 12; + +my $scale = 3; +my $total = sum0( map { $scale = 4-$scale; $scale * $_; } split(//,$isbn) ); +$total %= 10; +$total = 10-$total; +$total %= 10; + +say $total; diff --git a/challenge-162/duncan-c-white/perl/ch-2.pl b/challenge-162/duncan-c-white/perl/ch-2.pl new file mode 100755 index 0000000000..b4e9ec6c5a --- /dev/null +++ b/challenge-162/duncan-c-white/perl/ch-2.pl @@ -0,0 +1,181 @@ +#!/usr/bin/perl +# +# TASK #2 - Wheatstone-Playfair +# +# Implement encryption and decryption using the Wheatstone-Playfair cipher: +# +# https://en.wikipedia.org/wiki/Playfair_cipher +# +# Examples: +# +# (These combine I and J, and use X as padding.) +# +# encrypt("playfair example", "hide the gold in the tree stump") = "bmodzbxdnabekudmuixmmouvif" +# +# decrypt("perl and raku", "siderwrdulfipaarkcrw") = "thewexeklychallengex" +# +# MY NOTES: hmmm. Not too hard. +# + +use strict; +use warnings; +use feature 'say'; +use Getopt::Long; +use Function::Parameters; +use List::Util qw(min max); +use Data::Dumper; + +my $debug=0; +die "Usage: playfair-cipher [--debug] encrypt|decrypt sentence key\n" + unless GetOptions( "debug"=>\$debug ) && @ARGV==3; +my( $mode, $text, $key ) = @ARGV; +die "bad mode $mode\n" unless $mode eq "encrypt" || $mode eq "decrypt"; + +=pod + +=head2 my @table = make_table( $key ); + +Make the Playfair 5x5 table from the key. + +=cut +fun make_table( $key ) +{ + $key = uc($key); + $key =~ s/J/I/g; + $key =~ tr/ //d; + + my %used = (); # set of letters we've used + + my $tabstr; + foreach my $letter (split(//,$key)) + { + next if $used{$letter}; + $tabstr .= $letter; + $used{$letter}++; + } + $used{J}++ if $used{I}; + $used{I}++ if $used{J}; + + foreach my $letter ('A'..'Z') + { + next if $used{$letter}; + $tabstr .= $letter; + } + + # convert $tabstr to the final table.. + my $len = length($tabstr); + die "make_table: table string $tabstr (len $len) should be len 25\n" + unless $len == 25; + my @result = map { $tabstr =~ s/^(.....)//; $1; } 1..5; + return @result; +} + + +=pod + +=head2 my @pairs = split_pairs( $text ); + +Split $text into 2-letter pairs, obeying the special +Playfair rules described in the wikipedia page. + +=cut +fun split_pairs( $text ) +{ + $text = uc($text); + $text =~ tr/ //d; + my @result; + while( length($text)>0 ) + { + my $len = length($text); + my $fst = substr($text,0,1); + my $scd = $len>1 ? substr($text,1,1) : 'X'; + say "debug: text=$text, len=$len, fst=$fst, scd=$scd" if $debug; + if( $fst eq $scd ) + { + push @result, "${fst}X"; + $text =~ s/^.//; + } else + { + push @result, "$fst$scd"; + $text =~ s/^..?//; + } + } + return @result; +} + + +=pod + +=head2 my( $r, $c ) = find_in_table( $letter, $tableref ); + +Find $letter in the 5x5 table @$tableref, returning +the ( row, column ) position. + +=cut +fun find_in_table( $letter, $tableref ) +{ + $letter = 'I' if $letter eq 'J'; + foreach my $r (0..4) + { + foreach my $c (0..4) + { + return ( $r, $c ) if + $letter eq substr( $tableref->[$r], $c, 1 ); + } + } +} + + +=pod + +=head2 my $ecpair = e_d( $pair, $tableref, $mode ); + +Encrypt (or decrypt if $mode is 'decrypt') the +given 2-letter pair $pair, using $tableref as +a reference to the 5x5 table. Return the result. + +=cut +fun e_d( $pair, $tableref, $mode ) +{ + my $offset = 1; + $offset = -1 if $mode eq 'decrypt'; + + my $fst = substr($pair,0,1); + my $snd = substr($pair,1,1); + my( $fr, $fc ) = find_in_table( $fst, $tableref ); + my( $sr, $sc ) = find_in_table( $snd, $tableref ); + #die "debug e_d, pair=$pair, fst=$fst, snd=$snd, fr=$fr, fc=$fc, sr=$sr, sc=$sc\n"; + + if( $fr==$sr ) # on same row + { + $fc += $offset; $fc %= 5; + $sc += $offset; $sc %= 5; + return substr( $tableref->[$fr], $fc, 1 ). + substr( $tableref->[$fr], $sc, 1 ); + } elsif( $fc==$sc ) # on same column + { + $fr += $offset; $fr %= 5; + $sr += $offset; $sr %= 5; + return substr( $tableref->[$fr], $fc, 1 ). + substr( $tableref->[$sr], $fc, 1 ); + } else # form a rectangle + { + # (fr,fc) is one corner, (sr,sc) the other + return substr( $tableref->[$fr], $sc, 1 ). + substr( $tableref->[$sr], $fc, 1 ); + } +} + + +my @table = make_table( $key ); +#die Dumper \@table; + +my @pairs = split_pairs( $text ); +#die Dumper \@pairs; + +my $result = ""; +foreach my $pair (@pairs) +{ + $result .= e_d( $pair, \@table, $mode ); +} +say $result; |
