Below is the write-up review (only covers Perl 5) of the Perl Weekly Challenge #007 of all the submitted answers. You can read the original questions first to understand the details of these two challenges.
Challenge #1
If we read the question carefully, there are several steps to solve this problem. First, to find all niven number from 0 to 50 inclusively. Second, to find the sum of its digits of this range of number. Third, print all the niven number on their own line.
For first step, as 0 is not a niven number since it can be divided by zero, some solutions will skip this number and count the range from 1 instead. Participants who took such approach are Gustavo Chaves, Joelle Maslak, Andrezgz, and Dave Jacoby. The alternative approach is to check for the value of zero and skip it in the loop (Athanasius and Alicia Bielsa) or treat the number as boolean value (Ruben Westerberg and Maxim Nechaev).
The second step is to calculate the sum of its digits. There are two approach, calculate the sum of all the digits in the array using sum function of the module List::Util (Gustavo Chaves, Maxim Nechaev, Andrezgz, and Dave Jacoby) or without using external module (Ruben Westerberg, Athanasius, Joelle Maslak, Adam Russell, and Alicia Bielsa). Main difference is solution that uses List::Util are shorter compare to those without. Special mention of Adam Russell’s solution which binary summation to calculate the total sum.
do{
my @digits = split(//,$i);
my $digit_sum = unpack("%32C*", pack("C*", @digits));
if($i % $digit_sum == 0){
print "$i ";
$count++;
}
$i++;
} while($count < NIVEN_COUNT);
And lastly, the third step is to print these number, “each on their own line”. There are two camps of people here. Those who say (or CORE::say) it out (Gustavo Chaves, Joelle Maslak, Andrezgz, and Dave Jacoby) or those who print newline \n explicitly (Ruben Westerberg, Athanasius, Maxim Nechaev, and Alicia Bielsa).
Looking through all the solutions, you will notice developers have different coding personalities or styles and motivation. The solution by Ruben Westerberg which uses only essential core features with minimal dependencies was done so so it can fit into one-liner is a good example of his chosen approach.
Challenge #2
This question was quite complicated and the number of submission was lower compare to first question. Basically the solution can be divided into two steps. First, obtain and filter the necessary dictionary words. Second, build a graph and find the shortest ladder between two words using Dijkstra’s algorithm.
For the first step, Gustavo Chaves’ solution caught my attention because how clean and readable on preparing the necessary word list for generating the graph. How he generates the word list remind me of Unix pipeline. Each function filters the necessary word list from the previous function.
my ($source, $target) = map {lc} @ARGV;
my $length = length $source;
my @words =
uniq
sort
map {lc}
grep {length == $length}
path('/usr/share/dict/words')->lines({chomp => 1});
my @ladder = first_shortest_ladder($source, $target, \@words);
For the second step that build the graph from the word list and find the shortest path between two words, Maxim Nechaev provided us with the shortest and cleanest solution. This was achieved by using Graph::Undirected and Algorithm::Combinatorics to implement Dijkstra’s algorithm.
sub find_shortest_ladder
{
my ($word1, $word2, $words) = @_;
my $g = Graph::Undirected->new;
map { $g->add_vertex($_) } @$words;
my $len = length($words->[0]) - 1;
my $iter = combinations($words, 2);
while( my $pair = $iter->next ) {
my $diffs = 0;
foreach my $i (0..$len) {
$diffs++ if substr($pair->[0], $i, 1) ne substr($pair->[1], $i, 1);
last if $diffs == 2;
}
$g->add_edge( @$pair ) if $diffs == 1;
}
return $g->SP_Dijkstra($word1, $word2);
}
Related blog posts to this week challenges by the usual suspect.
- Laurent Rosenfeld’s post on both Perl 5 and 6 solutions.
- Arne Sommer’s post on step-by-step solutions using Perl 6.
- Jo Christian Oterhals’ post on Perl 6 solutions and usages.
- Adam Russell’s post on detailed explanation on his approach to solve both questions.
- Dave Jacoby’s post on simple solution to challenge #1 using both Perl and Javascript.