### Perl Weekly Challenge: Week 163

#### Challenge 1:

Sum Bitwise Operators

You are given a list of positive numbers, `@n`.

Write script to calculate the sum of bitwise & operator for all unique pairs.

##### Example 1:
``````Input: @n = (1, 2, 3)
Output: 3

Since (1 & 2) + (2 & 3) + (1 & 3) => 0 + 2 + 1 =>  3.
``````
##### Example 2:
``````Input: @n = (2, 3, 4)
Output: 2

Since (2 & 3) + (2 & 4) + (3 & 4) => 2 + 0 + 0 =>  2.
``````

In Raku we can solve this with a one-liner.

``````@*ARGS.combinations(2).map({ [+&] \$_ }).sum.say;
``````

(Full code on Github.)

`@*ARGS` are the arguments passed on the command line. These should be a list of positive numbers though I'm not actually checking that. We apply `.combinations(2)` to them to get unique pairs. Then `.map()` is used to apply bitwise and to each pair. (bitwise and is `+&` in Raku not just `&` which always trips me up.) I could have expressed this as `\$_[0] +& \$_[1]` but decided to use the hyperoperator `[+&]` instead. It just reads better IMO. At this point, we have a list of results of each and operation. These are totalled with `.sum()`. I could have used `[+]` but this allows me to continue chaining

In Perl, we have to be a bit more verbose as we are missing `.sum()` and `.combinations()` but I already had replacement functions for them and armed with those, the core part of the Perl solution is also one line.

``````say sum([map { \$_->[0] & \$_->[1] } combinations(\@ARGV, 2) ]);
``````

(Full code on Github.)

#### Challenge 2:

Summations

You are given a list of positive numbers, `@n`.

Write a script to find out the summations as described below.

##### Example 1:
``````Input: @n = (1, 2, 3, 4, 5)
Output: 42

1 2 3  4  5
2 5  9 14
5 14 28
14 42
42

The nth Row starts with the second element of the (n-1)th row.
The following element is sum of all elements except first element of previous row.
You stop once you have just one element in the row.
``````
##### Example 2:
``````Input: @n = (1, 3, 5, 7, 9)
Output: 70

1 3  5  7  9
3  8 15 24
8 23 47
23 70
70
``````

This one took me a little while to understand but ultimately proved to be quite straightforward to solve. According to the spec, the nth row begins with the (n-1)th element of the previous row. So we start the script with all the elements of the input except the first. I've called this new array `@previous` but in hindsight `@current` would have been more appropriate.

``````my @previous = @n[1 .. *];
``````

There is also a variable to store the running total.

``````my \$total;
``````

Now as long as there is atleast one element left in `@previous`...

``````while @previous.elems {
``````

We initalize `\$total` to the value of the first element.

``````    \$total = @previous[0];
``````

And set up an array to hold the next line. It is initialized with `\$total`.

``````    my @next = ( \$total );
``````

Then for each of the remaining elements in `@previous`, we add its value to `\$total` and add the new value of `\$total` to `@next`.

``````    for 1 ..^ @previous.elems -> \$i {
\$total += @previous[\$i];
@next.push(\$total);
}
``````

Finally, we make the new value of `@previous` equal to all the elements of `@next` except the first one.

``````    @previous = @next[1 .. *];
}
``````

After this loop finishes, `\$total` contains the final answer so we print it.

``````say \$total;
``````

(Full code on Github.)

For once, Perl has everything we need to translate the Raku code above. The syntax isn't even particularly ungainly compared to the Raku version.

``````my @previous = @n[1 .. \$#n];
my \$total;

while (scalar @previous) {
\$total = \$previous[0];
my @next = ( \$total );

for my \$i (1 .. scalar @previous - 1) {
\$total += \$previous[\$i];
push @next, \$total;
}

@previous = @next[1 .. \$#next];
}

say \$total;
``````

(Full code on Github.)