Perl Weekly Challenge 252: Special Numbers

These are some answers to the Week 252, Task 1, of the Perl Weekly Challenge organized by Mohammad S. Anwar.

Spoiler Alert: This weekly challenge deadline is due in a few days from now (on January 21, 2024 at 23:59). This blog post provides some solutions to this challenge. Please don’t read on if you intend to complete the challenge on your own.

Task 1: Special Numbers

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

Perl has a special variable to make an array 1-indexed instead of 0-indexed, but its use is rather dangerous and somewhat deprecated. I do not think that such feature exists in Raku. Both in Raku and Perl, we'll use 0-indexed arrays and add 1 to the subscript when required.

Special Numbers in Raku

We'll loop over the indexes and add the square of the value to an accumulator variable ($sq-sum) when the index (plus 1) evenly divides n, i.e. the number of items in the input array.

sub special-numbers (@in) {
    my $n = @in.elems;
    my $sq-sum = 0;
    for 0..@in.end -> $i {
        $sq-sum += @in[$i]² if $n %% ($i+1);
    }
    return $sq-sum;
}

for <1 2 3 4>, <2 7 1 19 18 3> -> @test {
    printf "%-15s => ", "@test[]";
    say special-numbers @test;
}

This program displays the following output:

$ raku ./spec-nums.raku
1 2 3 4         => 21
2 7 1 19 18 3   => 63

Special Numbers in Perl

This is a port to Perl of the above Raku program. Please loop at the previous section if you need further explanations.

use strict;
use warnings;
use feature 'say';

sub special_numbers {
    my @in = @_;
    my $n = scalar @in;
    my $sq_sum = 0;
    for my $i (0..$#in) {
        $sq_sum += $in[$i] ** 2 unless $n % ($i+1);
    }
    return $sq_sum;
}

for my $test ([<1 2 3 4>], [<2 7 1 19 18 3>]) {
    printf "%-15s => ", "@$test";
    say special_numbers @$test;
}

This program displays the following output:

$ perl ./spec-nums.pl
1 2 3 4         => 21
2 7 1 19 18 3   => 63

Wrapping up

The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on January 28, 2024. And, please, also spread the word about the Perl Weekly Challenge if you can.

Leave a comment

About laurent_r

user-pic I am the author of the "Think Perl 6" book (O'Reilly, 2017) and I blog about the Perl 5 and Raku programming languages.