Perl Weekly Challenge 252.

My solutions (task 1 and task 2 ) to the The Weekly Challenge - 252.

Task 1: Special Numbers

Submitted by: Mohammad S Anwar
You are given an array of integers, @ints.

Write a script to find the sum of the squares of all special elements of the
given array.


An element $int[i] of @ints is called special if i divides n, i.e. n % i == 0.
Where n is the length of the given array. Also the array is 1-indexed
for the task.

Example 1
Input: @ints = (1, 2, 3, 4)
Output: 21

There are exactly 3 special elements in the given array:
$ints[1] since 1 divides 4,
$ints[2] since 2 divides 4, and
$ints[4] since 4 divides 4.

Hence, the sum of the squares of all special elements of given array:
1 * 1 + 2 * 2 + 4 * 4 = 21.
Example 2
Input: @ints = (2, 7, 1, 19, 18, 3)
Output: 63

There are exactly 4 special elements in the given array:
$ints[1] since 1 divides 6,
$ints[2] since 2 divides 6,
$ints[3] since 3 divides 6, and
$ints[6] since 6 divides 6.

Hence, the sum of the squares of all special elements of given array:
2 * 2 + 7 * 7 + 1 * 1 + 3 * 3 = 63

A simple solution consists of filtering all possible indices, searching for divisors of the length of the array, and then squaring an adding the corresponding array elements. This may be done with a combination of grep, map and sum0. It all fits a oneliner.

Example 1:

perl -MList::Util=sum0 -E '@x=@ARGV;say "@x -> ", sum0 map{$x[$_-1]**2} grep {@x%$_==0} 1..@x;' 1 2 3 4

Results:

1 2 3 4 -> 21

Example 2:

perl -MList::Util=sum0 -E '@x=@ARGV;say "@x -> ", sum0 map{$x[$_-1]**2} grep {@x%$_==0} 1..@x;
' 2 7 1 19 18 3

Results:

2 7 1 19 18 3 -> 63

The full code is essentially the same:

 1  # Perl weekly challenge 252
 2  # Task 1:  Special Numbers
 3  #
 4  # See https://wlmb.github.io/2024/01/15/PWC252/#task-1-special-numbers
 5  use v5.36;
 6  use List::Util qw(sum0);
 7  die <<~"FIN" unless @ARGV;
 8      Usage: $0 N1 [N2...]
 9      to sum the squares of the special elements of N1 N2...
10      FIN
11  say "@ARGV -> ", sum0 map {$ARGV[$_-1]**2} grep {@ARGV%$_==0} 1..@ARGV;

Examples:

./ch-1.pl 1 2 3 4
./ch-1.pl 2 7 1 19 18 3

Results:

1 2 3 4 -> 21
2 7 1 19 18 3 -> 63

Task 2: Unique Sum Zero

Submitted by: Mohammad S Anwar
You are given an integer, $n.

Write a script to find an array containing $n unique integers such that
they add up to zero.

Example 1
Input: $n = 5
Output: (-7, -1, 1, 3, 4)

Two other possible solutions could be as below:
(-5, -1, 1, 2, 3) and (-3, -1, 2, -2, 4).
Example 2
Input: $n = 3
Output: (-1, 0, 1)
Example 3
Input: $n = 1
Output: (0)

I’m not quite sure I understood this problem, as there are many very simple solutions. For example, one could take any set of N-1 distinct positive numbers and add as the las element their sum with a minus sign. Thus I’ll add a little constraint, namely, to obtain the smaller possible solution, in the sense that the sum of the absolute values is minimum (assuming integer numbers). This is easily solved also. For N=1 the solution ls [0], for N=2 it is [-1,1]. For arbitrary N, I can solve the problem for N-2 and then add ±N/2. Equivalently, the solution is -N/2,-N/2+1...N/2-1,N/2 including 0 once if N is odd and excluding it if even.

Example 1

perl -E '$n=shift; say "$n -> [", join(" ", -$n/2..-1, $n%2?(0):(), 1..$n/2), "]"' 5

Results:

5 -> [-2 -1 0 1 2]

Example 2

perl -E '$n=shift; say "$n -> [", join(" ", -$n/2..-1, $n%2?(0):(), 1..$n/2), "]"' 3

Results:

3 -> [-1 0 1]

Example 3

perl -E '$n=shift; say "$n -> [", join(" ", -$n/2..-1, $n%2?(0):(), 1..$n/2), "]"' 1

Results:

1 -> [0]

Another example:

perl -E '$n=shift; say "$n -> [", join(" ", -$n/2..-1, $n%2?(0):(), 1..$n/2), "]"' 6

Results:

6 -> [-3 -2 -1 1 2 3]

The full code is similar.

 1  # Perl weekly challenge 252
 2  # Task 2:  Unique Sum Zero
 3  #
 4  # See https://wlmb.github.io/2024/01/15/PWC252/#task-2-unique-sum-zero
 5  use v5.36;
 6  die <<~"FIN" unless @ARGV;
 7      Usage: $0 N1 [N2...]
 8      to obtain arrays of N_j numbers that add up to zero.
 9      FIN
10  for(@ARGV){
11      warn("Input must be greater than one"), next unless $_>=1;
12      say "$_ -> [", join(" ", -$_/2..-1, $_%2?(0):(), 1..$_/2), "]";
13  }

Examples:

./ch-2.pl 1 2 3 4 5 6

Results:

1 -> [0]
2 -> [-1 1]
3 -> [-1 0 1]
4 -> [-2 -1 1 2]
5 -> [-2 -1 0 1 2]
6 -> [-3 -2 -1 1 2 3]
Written on January 15, 2024