## Perl Weekly Challenge 258: Sum of Values

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

Spoiler Alert: This weekly challenge deadline is due in a couple of days from now (on March 3, 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 2: Sum of Values

You are given an array of integers, `@int` and an integer `\$k`.

Write a script to find the sum of values whose index binary representation has exactly `\$k` number of 1-bit set.

Example 1

``````Input: @ints = (2, 5, 9, 11, 3), \$k = 1
Output: 17

Binary representation of index 0 = 0
Binary representation of index 1 = 1
Binary representation of index 2 = 10
Binary representation of index 3 = 11
Binary representation of index 4 = 100

So the indices 1, 2 and 4 have total one 1-bit sets.
Therefore the sum, \$ints[1] + \$ints[2] + \$ints[4] = 17
``````

Example 2

``````Input: @ints = (2, 5, 9, 11, 3), \$k = 2
Output: 11
``````

Example 3

``````Input: @ints = (2, 5, 9, 11, 3), \$k = 0
Output: 2
``````

### Sum of Values in Raku

Although it could easily be done in a one-liner, I've decided to split the solution in two statements, for the sake of clarity. The first statement finds the indexes whose binary representation contains exactly `\$k` "1" (sum of digits equal to `\$k`) and populates the `@eligibles` array with the corresponding input values in `@in`. The second statement simply returns the sum oh those values.

``````sub sum-of-values (\$k, @in) {
my @eligibles = map { @in[\$_] },
grep {\$_.base(2).comb.sum == \$k}, 0..@in.end;
return @eligibles.sum;
}

my @tests = (1, <2 5 9 11 3>),
(2, <2 5 9 11 3>),
(0, <2 5 9 11 3>);

for @tests -> @test {
printf "%-15s => ", "@test[]";
say sum-of-values @test[0], @test[1];
}
``````

This program displays the following output:

``````\$ raku ./sum-of-values.raku
1 2 5 9 11 3    => 17
2 2 5 9 11 3    => 11
0 2 5 9 11 3    => 2
``````

### Sum of Values in Perl

This is a port to Perl of the above Raku program. I counted the number of "1" using the `tr///` operator because has no built-in `sum` function, only to find moments later that I needed to implement a `sum` subroutine anyway.

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

sub sum {
my \$sum = 0;
\$sum += \$_ for @_;
return \$sum;
}

sub sum_of_values {
my (\$k, @in) = @_;
my @eligibles = map { \$in[\$_] }
grep {sprintf ("%b", \$_) =~ tr/1/1/  == \$k} 0..\$#in;
return sum @eligibles;
}

my @tests = ( [1, [<2 5 9 11 3>]],
[2, [<2 5 9 11 3>]],
[0, [<2 5 9 11 3>]] );

for my \$test (@tests) {
printf "%-3s - %-15s  => ", "\$test->[0]", "@{\$test->[1]}";
say sum_of_values \$test->[0], @{\$test->[1]};
}
``````

This program displays the following output:

``````\$ perl ./sum-of-values.pl
1   - 2 5 9 11 3       => 17
2   - 2 5 9 11 3       => 11
0   - 2 5 9 11 3       => 2
``````

## 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 March 10, 2024. And, please, also spread the word about the Perl Weekly Challenge if you can.