with Raku

This is my response to The Weekly Challenge #252.

You are given an array of integers,

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

An element

Example 1:

File: special-numbers
`@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

#! /usr/bin/env raku
unit sub MAIN (*@ints where @ints.elems > 0 && all(@ints) ~~ Int, # [1]
:v(:$verbose));
my $sum = 0; # [2]
my $n = @ints.elems; # [3]
for 1 .. $n -> $i # [4]
{
if $n %% $i # [5]
{
my $val = @ints[$i -1]; # [6]
my $squared = $val ** 2; # [7]
$sum += $squared; # [8]
say ": Index $i is special -> value:$val -> squared:$squared -> sum:$sum"
if $verbose;
}
}
say $sum; # [9]

[1] At least one value, and they must all be integers.

[2] The sum will be added up here.

[3] The number of elements (and the highest 1-based index).

[4] Iterate over the 1-based indices.

[5] Is the number of items divisable (the `%%`

operator) by the
index.

See docs.raku.org/routine/%% for more information about the Divisibility Operator `%%`

.

[6] Get the value at the current index.

[7] Square the value.

[8] Add that square to the sum.

[9] Print the result.

Running it:

$ ./special-numbers 1 2 3 4
21
$ ./special-numbers 2 7 1 19 18 3
63

Looking good.

With verbose mode:

$ ./special-numbers -v 1 2 3 4
: Index 1 is special -> value:1 -> squared:1 -> sum:1
: Index 2 is special -> value:2 -> squared:4 -> sum:5
: Index 4 is special -> value:4 -> squared:16 -> sum:21
21
$ ./special-numbers -v 2 7 1 19 18 3
: Index 1 is special -> value:2 -> squared:4 -> sum:4
: Index 2 is special -> value:7 -> squared:49 -> sum:53
: Index 3 is special -> value:1 -> squared:1 -> sum:54
: Index 6 is special -> value:3 -> squared:9 -> sum:63
63

You are given an integer,

Write a script to find an array containing

Example 1:

`$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)

Random numbers, as used in the examples, only add complexity (and entropy - which makes testing complicated). So let us not go that way.

File: usz#! /usr/bin/env raku
unit sub MAIN (UInt $n is copy, :v(:$verbose)); # [1]
my @array; # [2]
if $n % 2 # [3]
{
@array = (0,); # [4]
say ": Odd number, added middle zero" if $verbose;
}
for 1 .. $n div 2 -> $i # [5]
{
@array.push: $i; # [6]
@array.unshift: -$i; # [7]
say ": Added { -$i } at front and $i at end" if $verbose;
}
say "({ @array.join(", ") })"; # [8]

[1] Ensure that the input is of the `UInt`

(Unsigned Int)
type.

See docs.raku.org/type/UInt for more information about the `UInt`

type.

[2] The result will end up here, presorted.

[3] Do we have an odd number (and thus an odd number of resulting values)?

[4] Add a zero in the middle.

[5] Iterate over half the number of values to add (integer divison
with `div`

does the trick), as values 1, 2
and so on.

See docs.raku.org/routine/div for more information about `div`

.

[6] Add the positive version to the **end** of the result.

[7] Add the negative version to the **beginning** of the result.

[8] Pretty print the result.

Running it:

$ ./usz 5
(-2, -1, 0, 1, 2)
$ ./usz 3
(-1, 0, 1)
$ ./usz 1
(0)

Looking good.

With verbose mode:

$ ./usz -v 5
: Odd number, added middle zero
: Added -1 at front and 1 at end
: Added -2 at front and 2 at end
(-2, -1, 0, 1, 2)
$ ./usz -v 3
: Odd number, added middle zero
: Added -1 at front and 1 at end
(-1, 0, 1)
$ ./usz -v 1
: Odd number, added middle zero
(0)

Let us try an even number, giving us an array without a zero in the middle:

$ ./usz -v 6
: Added -1 at front and 1 at end
: Added -2 at front and 2 at end
: Added -3 at front and 3 at end
(-3, -2, -1, 1, 2, 3)

And that's it.