Kian-Meng Ang Weekly Review: Challenge - 015

Saturday, Jul 13, 2019| Tags: Perl

Continues from previous week.

Feel free to submit a merge request or open a ticket if you found any issues with this post. Feedback are very much appreciated and welcome.

For a quick overview, read the original questions and recap of the weekly challenge.

Since this question is related to Perl Weekly Challenge #12, quite a few participants (Adam Russell, Jaldhar H. Vyas, Yozen Hernandez, E. Choroba, and others) were using and adapting their answer from Perl Weekly Challenge #12.

While the question mentioned about strong and weak primes, some participants (Athanasius, E.Choroba, Duane Powell, and Ruben Westerberg) took initiative to include balance primes as well.

Veesh Goldman’s submitted answer was the only solution that was written in a way that matches the suggested formulae.

``````    #an interface to our generator. Returns the prime at number n if it exists,
#and otherwise expands the list until there is a prime at that number
sub p {
my \$n = shift;
state \$top = 0;
#if there's an entry at this number, then return it
return \$primes[\$n] if \$primes[\$n];
#otherwise, generate more numbers and then return it
until (\$primes[\$n]) {
generate_primes_till (\$top+=1000)
}
}

sub is_strong {
my \$n = shift;
p(\$n) > ( p(\$n-1) + p(\$n+1) ) /2
}
``````

Simon Miner use of regex to generate the prime numbers was rather distinctive. Yes, the infamous Perl’s one-liner approach which was due to Abigail of Perl fame.

``````    my @primes = grep( { ( 1 x \$_ ) !~ /^1?\$|^(11+?)\1+\$/ } 1 .. 101 );
``````

Similarly, Daniel Mantovani used another variation of the regex to check for prime numbers.

``````    sub is_prime {
return ( 7 x shift ) !~ /^(77+)\1+\$/;
}
``````

Instead of filtering prime numbers by type using if-else as shown in Laurent Rosenfeld’s second example in non-functional implementation), we can use Perl’s numeric comparison operator `<=>` instead. The comparison operator will return -1, 0, 1 for if the left number is less than, equal to, or more than the right number. For example, looking at E. Choroba’s code as shown below.

``````    my \$p = 'My::Primes'->new;
my (@strong, @weak, @balanced);
while (@strong < 10 || @weak < 10) {
\$p->grow;
push @{
(\@balanced, \@strong, \@weak)[
\$p->[-2] <=> (\$p->[-3] + \$p->[-1]) / 2 ]
}, \$p->[-2];
}
``````

Both Ruben Westerberg and Yozen Hernandez took similar way as well. However, we found Yozen’s code more readable, due to the use of postfix dereference syntax.

``````    while ( ( @strong_primes < \$n ) || ( @weak_primes < \$n ) ) {
push @primes, \$iter->();
if ( @primes > 2 ) {
push \$which_arr[ ( \$primes[-2] <=> ( \$primes[-3] + \$primes[-1] ) / 2 ) ]->@*, \$primes[-2];
}
}
``````

If we remember correctly, there were a few participants who prefer to use postfix dereference syntax, which was first introduced in Perl v5.20, in the their solutions. In Athanasius’s solution shown below, notice the postfixed sigil-and-star, `@*`. Judging from lack of pragma being declared, we assumed Athanasius must be running at least Perl v5.24 or later where this feature was declared as stable.

``````    while (scalar \$primes{strong}->@* < \$SERIES_LENGTH ||
scalar \$primes{weak  }->@* < \$SERIES_LENGTH)
``````

Recommended books to read for this challenge are Making, Breaking Codes: Introduction to Cryptology (via Adam Russell) and Applied Cryptography (via Dave Jacoby).

Some notable solutions that caught our attention.

Veesh Goldman have created a read–eval–print loop (REPL) in his solution for encoding and decoding a message. The use of callback in implementing the loop was a good example on how to implement a pluggable code. And he also discovered that you can interpolate function within a string. And as the comment suggested, the use of `shift` function was quite compulsive in his codes.

``````    #i recently found out that you can take a reference to a function
#inside of an interpolation, so it's creeping in everywhere I
#write code
sub die_usage { die "\${\shift} \n \$usage" }
``````

It was assumed that most solutions will use `chr` and `ord` function (faster based on Steven Wilson’s benchmark) to implement the encryption and decryption. Yet, solutions using lookup table were equivalent the same which was used by Yozen Hernandez, Roger Bell West, Ruben Westerberg, Athanasius, Andrezgz, Dave Jacoby and Jaldhar H. Vyas.

Duane Powell was the only participant who used `pack` and `unpack` function (often misunderstood functions but there is a good tutorial to clear things up) to solve the problem.

Walt Mankowski’s solution for this challenge was a good starting code to read to have a quick overview of the problem. It’s concise and clean, hence easy for understanding the formulae. It’s also a good example on how to use and process the command line options in a simple manner.

Similarly, E Choroba’s solution was elegantly coded and production ready. Set a cipher key to the package and you can decode and encode at the same time. Moreover, the solution also came with test cases.

We have nine participants submitted their answers in Perl 5 or Perl 6 to this week challenge.

For Perl 5, we have Dave Jacoby, Athanasius, Neil Bowers, Guillermo Ramos, Steven Wilson, Veesh Goldman and lastly the regular Joelle Maslak.

For Perl 6, we see participation from Athanasius, Francis Whittle and again Joelle Maslak.

In the past, when we were reviewing the submitted answers for Task #3, we were wondering who will create a CPAN module and submitted a solution based on that CPAN module. And we finally have one submission from Neil Bowers. He basically created a `WebService::DetectLanguage` CPAN module and use that module in his answer.

Now, we are wondering who else will create the same for Perl 6’s solution for upcoming API Task #3?

Should it be done for Perl 6?

Well, yes and no.

Yes, because we would like to see a Perl 6 module created for this challenge.

No, because Athanasius have shown us that you can actually use Perl 5 module in Perl 6 code as shown in his Perl 6 solution shown below. We believed Athanasius took this approach to reuse code from both Perl 5 and Perl 6. See the Perl 5 solution for comparison. Joelle Maslak also took a similar and usual approach but on the code structure rather than the module used as seen in the Perl 5 and Perl 6 solution.

``````    use JSON::Tiny;
use LWP::UserAgent:from<perl5> ();
......
my \$ua = LWP::UserAgent.new(timeout => \$TIMEOUT);
my \$response = \$ua.post(\$URL-DETECT, Content => "q=\$text");
``````

Basically, you can call the Perl 5 CPAN module in Perl 6 through wrapper by the `Inline::Perl5` module. While it seemed stable enough, there are still some workarounds. Nevertheless, the dot notation to call a subroutine was a nice syntactic sugar. Similarly, we can also call Perl 6 code in Perl 5 through another CPAN module, `Inline::Perl6`.

Blog Posts

Regular write-up by some of the participants.

(1) Prime Vigenere and Perl 6 by Arne Sommer.

If you want to read step-by-step walk through for both challenges in Perl 6, then his blog is a must read. Especially if you stuck with a problem, his solutions is a good reference point even for Perl 5.

(2) Perl Weekly Challenge 015 by Adam Russell.

Prolific member who managed to submit answers and blog about it after a long vacation.

(3) Perl Weekly Challenge 015 by Dave Jacoby.

Very detailed write-up on how he solve the Task #2, the cryptography that prevent your sister peeking at your stuff.

(4) Perl Weekly Challenge # 15: Strong and Weak Primes and Vigenère Encryption by Laurent Rosenfeld.

Comparison of Perl 6 and Perl 5 solutions where Perl 6 seemed to have certain advantages. Also, a very detailed analysis on Task #2. Recommended read of the week.

(5) Functional Programming in Perl: Strong and Weak Primes (Perl Weekly Challenge) by Laurent Rosenfeld.

Follow up on the previous post with focus on functional programming which includes anonymous subroutines, closures, and iterators. Another recommended read of the week.

(6) Perl Weekly Challenge: Week 15 by Jaldhar H. Vyas.

Another post on the comparison of Perl 5 and Perl 6 solutions.

(7) An interface to the DetectLanguage API by Neil Bowers.

Another week, another CPAN module released by Neil Bowers. For those who haven’t participate in Task #3, read his blog post.

(8) Perl Weekly Challenge 15, Part 1: Finding Strong and Weak Primes with Perl by Yozen Hernandez.

Another participant who tried with iterator and `Memoize` CPAN module.

(9) Perl Weekly Challenge 15, Part 2: Encrypting/Decrypting With the Vigenère Cipher by Yozen Hernandez.

If you want another view on solving Task #2.

(10) Benchmarking my Vigenère cipher code by Steven Wilson.

Steven took another approach in solving Task #2 by benchmarking different implementations to find the optimum solution. Recommended read of the week.