# Sum and Sum Againwith Raku and Perl

by Arne Sommer
[182] Published 8. May 2022.

This is my response to the Perl Weekly Challenge #163.

## Challenge #163.1: Sum Bitwise Operator

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. ```

I do believe that «Positive numbers» should be read as «Postive integers».

File: sbo ```#! /usr/bin/env raku unit sub MAIN (*@values where @values.elems > 0 && all(@values) ~~ /^<[1..9]><[0..9]>*\$/, # [1] :v(:\$verbose)); if \$verbose { say ": Combinations: { @values.combinations(2) .map({ "(" ~ \$_[0] ~ "," ~ \$_[1] ~ ")" } ) }"; say ": Mapped to: { @values.combinations(2).map({ \$_[0] ~& \$_[1]} ) }"; } say @values.combinations(2).map({ \$_[0] ~& \$_[1]} ).sum; # [2] ```

[1] Note the regex to ensure a postivie integer, without a leading zero.

[2] We use `combinations(2)` to get all the unique combinations of length 2. Then we use `map` to bitwise AND (the `~&` operator) the two values together, and finaly we use `.sum` to add the values together.

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

See docs.raku.org/language/operators#index-entry-Numeric_bitwise_AND_operator for more information about the numeric bitwise AND operator `~&`.

Running it:

```\$ ./sbo 1 2 3 3 \$ ./sbo 2 3 4 2 ```

With verbose mode:

```\$ ./sbo -v 1 2 3 : Combinations: (1,2) (1,3) (2,3) : Mapped to: 0 1 2 3 \$ ./sbo -v 2 3 4 : Combinations: (2,3) (2,4) (3,4) : Mapped to: 2 0 0 2 ```

### A Perl Version

This is straight forward translation of the Raku version, using modules to get `all`, `sum` and `combinations`.

File: sbo-perl ```#! /usr/bin/env perl use strict; use warnings; use feature 'say'; use Getopt::Long; use Perl6::Junction 'all'; use List::Util qw(sum); use Algorithm::Combinatorics qw(combinations); my \$verbose = 0; GetOptions("verbose" => \\$verbose); my @values = @ARGV; die "Please specify a list of positve integers" unless @values; die "Integers only" unless qr/^[1-9][0-9]*\$/ == all(@values); my \$sum = 0; for my \$pair (combinations(\@values, 2)) { my \$and = \$pair->[0] & \$pair->[1]; \$sum += \$and; say ": Pair: \$pair->[0], \$pair->[1] (-> \$and)" if \$verbose; } say \$sum; ```

Running it gives the same result as the Raku version, except for a slightly different verbose output:

```\$ ./sbo-perl -v 1 2 3 : Pair: 1, 2 (-> 0) : Pair: 1, 3 (-> 1) : Pair: 2, 3 (-> 2) 3 \$ ./sbo-perl -v 2 3 4 : Pair: 2, 3 (-> 2) : Pair: 2, 4 (-> 0) : Pair: 3, 4 (-> 0) 2 ```

## Challenge #163.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 ```

I do believe that «Positive numbers» should be read as «Postive integers», as in the first part of the challenge.

File: summations ```#! /usr/bin/env raku unit sub MAIN (*@values where @values.elems > 0 && all(@values) ~~ /^<[1..9]><[0..9]>*\$/, :v(:\$verbose)); while @values.elems > 1 # [1] { say ": @values[]" if \$verbose; @values = next-row(@values); # [2] } say @values[0]; # [3] sub next-row (@values) { my @new; for (1 .. @values.elems -1) -> \$index # [4] { @new.push: @values[1..\$index].sum; # [5] } return @new; # [6] } ```

[1] As long as there are more than 1 element in the array,

[2] Transform the array to the next version (with one element less).

[3] Print the remaining element.

[4] For each index in the incoming array (except zero),

[5] Get the sum of all the elements from index 1 to the current index, and add that to the new list.

[6] Return the new list.

Running it:

```\$ ./summations 1 2 3 4 5 42 \$ ./summations 1 3 5 7 9 70 ```

With verbose mode:

```\$ ./summations -v 1 2 3 4 5 : 1 2 3 4 5 : 2 5 9 14 : 5 14 28 : 14 42 42 \$ ./summations -v 1 3 5 7 9 : 1 3 5 7 9 : 3 8 15 24 : 8 23 47 : 23 70 70 ```

### Perl

This is a straight forward translation of the Raku version.

File: summations-perl ```#! /usr/bin/env perl use strict; use warnings; use feature 'say'; use Getopt::Long; use Perl6::Junction 'all'; use List::Util qw(sum); use feature 'signatures'; no warnings qw(experimental::signatures); my \$verbose = 0; GetOptions("verbose" => \\$verbose); my @values = @ARGV; die "Please specify a list of positve integers" unless @values; die "Integers only" unless qr/^[1-9][0-9]*\$/ == all(@values); while (@values > 1) { say ": @values" if \$verbose; @values = next_row(@values); } say \$values[0]; sub next_row (@values) { my @new; for my \$index (1 .. @values -1) { push(@new, sum(@values[1..\$index])); } return @new; } ```

Running it gives the same result as the Raku version:

```\$ ./summations-perl 1 2 3 4 5 42 \$ ./summations-perl -v 1 3 5 7 9 70 ```

With verbose mode:

```\$ ./summations-perl -v 1 2 3 4 5 : 1 2 3 4 5 : 2 5 9 14 : 5 14 28 : 14 42 42 \$ ./summations-perl -v 1 3 5 7 9 : 1 3 5 7 9 : 3 8 15 24 : 8 23 47 : 23 70 70 ```

And that's it.