Perl Weekly Challenge 238.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 238.
Task 1: Running Sum
Submitted by: Mohammad S Anwar
You are given an array of integers.
Write a script to return the running sum of the given array.
The running sum can be calculated as sum[i] = num[0] + num[1] + …. + num[i].
Example 1
Input: @int = (1, 2, 3, 4, 5)
Output: (1, 3, 6, 10, 15)
Example 2
Input: @int = (1, 1, 1, 1, 1)
Output: (1, 2, 3, 4, 5)
Example 3
Input: @int = (0, -1, 1, 2)
Output: (0, -1, 0, 2)
List::Util
provides the function reductions
which produces the
partial reductions of a list by an arbitrary binary operation, not
only the final reduction over the whole list. In this case, we are
asked for the running reduction using the sum. This leads to a very
simple one-liner.
Example 1:
perl -MList::Util=reductions -E '
say "@ARGV -> ", join " ", reductions {$a+$b} @ARGV
' 1 2 3 4 5
Results:
1 2 3 4 5 -> 1 3 6 10 15
Example 2:
perl -MList::Util=reductions -E '
say "@ARGV -> ", join " ", reductions {$a+$b} @ARGV
' 1 1 1 1 1
Results:
1 1 1 1 1 -> 1 2 3 4 5
Example 3:
perl -MList::Util=reductions -E '
say "@ARGV -> ", join " ", reductions {$a+$b} @ARGV
' 0 -1 1 2
Results:
0 -1 1 2 -> 0 -1 0 2
The full code is almost identical.
1 # Perl weekly challenge 238
2 # Task 1: Running Sum
3 #
4 # See https://wlmb.github.io/2023/10/09/PWC238/#task-1-running-sum
5 use v5.36;
6 use List::Util qw(reductions);
7 die <<~"FIN" unless @ARGV;
8 Usage: $0 N1 [N2...]
9 to return the running sum N1, N1+N2, N1+N2+N3...
10 of the numbers N1, N2...
11 FIN
12 say "@ARGV -> ", join " ", reductions {$a+$b} @ARGV
Examples:
./ch-1.pl 1 2 3 4 5
./ch-1.pl 1 1 1 1 1
./ch-1.pl 0 -1 1 2
Results:
1 2 3 4 5 -> 1 3 6 10 15
1 1 1 1 1 -> 1 2 3 4 5
0 -1 1 2 -> 0 -1 0 2
Task 2: Persistence Sort
Submitted by: Mohammad S Anwar
You are given an array of positive integers.
Write a script to sort the given array in increasing order with
respect to the count of steps required to obtain a single-digit
number by multiplying its digits recursively for each array element.
If any two numbers have the same count of steps, then print the
smaller number first.
Example 1
Input: @int = (15, 99, 1, 34)
Output: (1, 15, 34, 99)
15 => 1 x 5 => 5 (1 step)
99 => 9 x 9 => 81 => 8 x 1 => 8 (2 steps)
1 => 0 step
34 => 3 x 4 => 12 => 1 x 2 => 2 (2 steps)
Example 2
Input: @int = (50, 25, 33, 22)
Output: (22, 33, 50, 25)
50 => 5 x 0 => 0 (1 step)
25 => 2 x 5 => 10 => 1 x 0 => 0 (2 steps)
33 => 3 x 3 => 6 (1 step)
22 => 2 x 2 => 4 (1 step)
I make a function to evaluate the number of steps to get one digit
using split
and product
repeatedly and
use it as a first test in a sort. The solution fits a simple two-liner.
Example 1:
perl -MList::Util=product -E '
sub f($x){$r=0;++$r,$x=product split "", $x while($x>=10); $r}
say "@ARGV -> ", join " ", sort {f($a)<=>f($b)||$a<=>$b} @ARGV
' 15 99 1 34
Results:
15 99 1 34 -> 1 15 34 99
Example 2:
perl -MList::Util=product -E '
sub f($x){$r=0;++$r,$x=product split "", $x while($x>=10); $r}
say "@ARGV -> ", join " ", sort {f($a)<=>f($b)||$a<=>$b} @ARGV
' 50 25 33 22
Results:
50 25 33 22 -> 22 33 50 25
It is interesting to note that the process of reducing a number by multiplying its digits always converges, as the product of the decimal digits of an integer is always smaller than the number itself.
The full code is almost identical, except for a few checks.
1 # Perl weekly challenge 238
2 # Task 2: Persistence Sort
3 #
4 # See https://wlmb.github.io/2023/10/09/PWC238/#task-2-persistence-sort
5 use v5.36;
6 use List::Util qw(product all);
7 use POSIX qw(floor);
8 sub steps($x){
9 my $result=0;
10 ++$result , $x=product split "", $x
11 while($x>=10);
12 $result
13 }
14 die <<~"FIN" unless @ARGV;
15 Usage: $0 N1 [N2...]
16 to sort the list N1 N2 according to the number of steps required
17 to bring the number to one digit and then according to value
18 FIN
19 die "Only natural numbers allowed" unless all {0<=floor($_)&&floor($_)==$_} @ARGV;
20 say "@ARGV -> ", join " ",
21 sort {steps($a)<=>steps($b)||$a<=>$b} @ARGV
Examples:
./ch-2.pl 15 99 1 34
./ch-2.pl 50 25 33 22
Results:
15 99 1 34 -> 1 15 34 99
50 25 33 22 -> 22 33 50 25
/;