From 11ce61d5df739402e98a4043d4b1f6682dccdea5 Mon Sep 17 00:00:00 2001 From: drbaggy Date: Mon, 2 May 2022 10:30:21 +0100 Subject: pushing new code and README.md --- challenge-163/james-smith/README.md | 108 +++++++++++++++++++++------------ challenge-163/james-smith/blog.txt | 1 + challenge-163/james-smith/perl/ch-2.pl | 4 +- 3 files changed, 71 insertions(+), 42 deletions(-) create mode 100644 challenge-163/james-smith/blog.txt diff --git a/challenge-163/james-smith/README.md b/challenge-163/james-smith/README.md index 248d432347..0c8c17cdc5 100644 --- a/challenge-163/james-smith/README.md +++ b/challenge-163/james-smith/README.md @@ -1,6 +1,6 @@ -[< Previous 161](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-161/james-smith) | -[Next 163 >](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-163/james-smith) -# The Weekly Challenge 162 +[< Previous 162](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-162/james-smith) | +[Next 164 >](https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-164/james-smith) +# The Weekly Challenge 163 You can find more information about this weeks, and previous weeks challenges at: @@ -12,58 +12,86 @@ submit solutions in whichever language you feel comfortable with. You can find the solutions here on github at: -https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-162/james-smith +https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-163/james-smith -# Challenge 1 - Validate ISBN-13 +# Challenge 1 - Sum bitwise operator -***Write a script to generate the check digit of given ISBN-13 code. Checksum is generated by summing the numbers in the odd positions with 3 times the sum of the numbers in the even positions. The checksum digit is the number you would add to get a total of 0*** +***You are given list positive numbers, `@n`. Write script to calculate the sum of bitwise `&` operator for all unique pairs.*** ## The solution -Rather than computing the checksum - as we have ISBN numbers with the checksum we will validate the numbers {checking the checksum calculated is equal to the last digit in the ISNB number]. +As with all code there is: + + * an initial phase where we set the sum to 0. + * a processing phase where we compute the sum: + * In this we repeatedly shift the first element of the list and: + * and it with all remaining elements keeping the sum. + * a final phase where we just return this sum. + +If we can't guarantee there are no duplicates in the list we add an +extra part to the initial phase to remove these duplicates. + +This gives us: ```perl -sub validate_isbn13 { - my @p = ( my $s = 0, grep {/\d/} split //, $_[0] ); - $s += 3*shift(@p) + shift @p while @p; - !($s%10); -} +sub bit_sum_compact { + my $t = 0; + + my %hash = map { $_ => 1 } @_; + @_ = keys %hash; -sub checksum_isbn13 { - my($s,@p) = ( 0, @{[grep {/\d/} split //, $_[0]]}[0..11] ); ## Remove checksum if present.. - $s -= shift(@p) + 3*shift @p while @p; - $s%10; + while(@_>1) { + my $a = shift; + $t+= $a&$_ for @_; + } + + $t; } + +``` + +# Challenge 2 - Summations + +***You are given a list of positive numbers, `@n`. Write a script to find out the summations as described below.*** + +## Solution. + +For a given row we drop the first element, then the remaining cells are the cumulative sum of the previous row. *e.g.* + +``` + a b c d + b b+c b+c+d + b+c b+c+b+c+d + b+c+b+c+d = 2b+2c+d ``` -# Challenge 2 - Wheatstone-Playfair +Similarly to the first element we at each interation shift of the first element. -***Implement encryption and decryption using the Wheatstone-Playfair cipher.*** + * This time our initial phase is empty (except for showing the input when dumping the table) + * Our loop phase: + * throws away the first entry (`shift`) + * initializes the cumulative sum (`t=0`) + * computes the next row `@_ = map { $t+$_ } @_` + * {we just `say @_` at each loop if we want to see the table} + * The final stage again just returns the last element of the array - the total we want. -I'm not going to try and explain this here - but refer you to wikipedia https://en.wikipedia.org/wiki/Playfair_cipher +```perl +sub summation_with_table { + my $t; + say "@_"; + shift, ($t=0), say join ' ', @_ = map { $t+=$_ } @_ while @_>1; + shift; +} +``` -First we note the only difference between encryption and decryption is the direction we move left->right up->down of *vv*, so we can implement these with a single "function" and two wrappers "emcrypt" and "decrypt". Often two way ciphers have this feature. +If we don't need the table but just the final value at the end, we can simplify this to: -We first create a hash and array which map the letter to their position and their position to the letter. This makes the future calculations easier ```perl -sub encrypt { return _crypt( 1,@_); } -sub decrypt { return _crypt(-1,@_); } - -sub _crypt { - my($off,$key,$p,$out,@r,%l) = (shift,shift,0,''); ## Initialise variables and get mapping... - ($_ eq 'j' && ($_='i')), exists $l{$_} || ($l{$_}=[int $p/5,($p++)%5]) for grep { /[a-z]/ } split(//,$key),'a'..'i','j'..'z'; - $r[$l{$_}[0]][$l{$_}[1]]=$_ for keys %l; - - my @seq = grep {/[a-z]/} split //, shift =~ s{j}{i}gr; ## Prep sequence - - while(my($m,$n)=splice @seq,0,2) { ## Loop through letter pairs - unshift(@seq,$n), $n='x' if $n && $n eq $m and $n ne 'x'; ## Deal with case when both letters the same - $n ||= 'x'; ## Pad if required... - $out.= $l{$m}[0] eq $l{$n}[0] ? $r[ $l{$m}[0] ][($l{$m}[1]+$off)%5] . $r[ $l{$n}[0] ][($l{$n}[1]+$off)%5] - : $l{$m}[1] eq $l{$n}[1] ? $r[($l{$m}[0]+$off)%5][ $l{$m}[1] ] . $r[($l{$n}[0]+$off)%5][ $l{$n}[1] ] - : $r[ $l{$m}[0] ][ $l{$n}[1] ] . $r[ $l{$n}[0] ][ $l{$m}[1] ] - ; - } - $out; +sub summation { + my $t; + shift, ($t=0), @_ = map { $t+=$_ } @_ while @_>1; + shift; } ``` + +In both these challenges we use the *perl*ism that within a postfix loop we can stitch together multiple statements into a single statement by the use of `,` (or any operator usually `||`, `&&` or `?:`). This leaves the beauty of the postfix loop while allowing multiple statements. diff --git a/challenge-163/james-smith/blog.txt b/challenge-163/james-smith/blog.txt new file mode 100644 index 0000000000..e7832a6a47 --- /dev/null +++ b/challenge-163/james-smith/blog.txt @@ -0,0 +1 @@ +https://github.com/drbaggy/perlweeklychallenge-club/tree/master/challenge-163/james-smith diff --git a/challenge-163/james-smith/perl/ch-2.pl b/challenge-163/james-smith/perl/ch-2.pl index 8430c3609a..63b36970ab 100644 --- a/challenge-163/james-smith/perl/ch-2.pl +++ b/challenge-163/james-smith/perl/ch-2.pl @@ -22,12 +22,12 @@ say ''; sub summation_with_table { my $t; say "@_"; - shift, ($t=0), say "@{[ @_ = map { $t+=$_ } @_ ]}" while @_>1; + shift, ($t=0), say join ' ', @_ = map { $t+=$_ } @_ while @_>1; shift; } sub summation { my $t; - shift, ($t=0), (@_ = map { $t+=$_ } @_) while @_>1; + shift, ($t=0), @_ = map { $t+=$_ } @_ while @_>1; shift; } -- cgit