### Perl Weekly Challenge: Week 244

#### Challenge 1:

**Count Smaller**

You are given an array of integers.

Write a script to calculate the number of integers smaller than the integer at each index.

##### Example 1

```
Input: @int = (8, 1, 2, 2, 3)
Output: (4, 0, 1, 1, 3)
For index = 0, count of elements less 8 is 4.
For index = 1, count of elements less 1 is 0.
For index = 2, count of elements less 2 is 1.
For index = 3, count of elements less 2 is 1.
For index = 4, count of elements less 3 is 3.
```

##### Example 2

```
Input: @int = (6, 5, 4, 8)
Output: (2, 1, 0, 3)
```

##### Example 3

```
Input: @int = (2, 2, 2)
Output: (0, 0, 0)
```

For the past few months, I have been giving myself the extra challenge of solving these tasks in one line; more often than not, I can do it. I thought this would be one of those times.

```
my %s=@*ARGS.sort Z=>@*ARGS.keys;say q{(},@*ARGS.map({ %s{$_}}).join(q{, }),q{)};
```

There are two statements in the line above. The first creates a hash whose keys are
the sorted elements of the command-line input and the values are the indices of those
elements. This is done via the `Z=>`

operator where `Z`

takes consecutive elements from each of the arrays that are its' operands and `=>`

converts them into a `Pair`

suitable
for insertion into a hash. The second statement iterates through the input with `.map()`

and for each element, returns the value from `%s`

for which that element is a key. (The
rest of the statement is just for pretty-printing the results.)

Unfortunately, for example 1, it gives us this:

```
(4, 0, 2, 2, 3)
```

Which is not quite right. The problem is that because 2 is repeated in the input. the first time the key `%s{2}`

gets the proper value 1, but the second time, it is overwritten with 2. In this short piece of code there is no way of saying don't assign a key-value pair if the key already exists.

So I had to rewrite things in a more verbose way.

```
my %s;
for @int.sort Z=> @int.keys -> $p {
```

This time we check that a key doesn't already exist before trying to assign a value to it.

```
unless %s{$p.key}:exists {
%s{$p.key} = $p.value;
}
}
say q{(}, @int.map({ %s{$_} }).join(q{, }), q{)};
```

And now we get the correct answer.

This is the Perl version. It has to be even more verbose as we don't have Raku
conveniences such as `Z=>`

and `.keys()`

.

```
my %s;
my $index = 0;
for my $elem (sort { $a <=> $b } @int) {
unless (exists $s{$elem}) {
$s{$elem} = $index;
}
$index++;
}
say q{(}, (join q{, }, map { $s{$_} } @int), q{)};
```

#### Challenge 2:

**Group Hero**

You are given an array of integers representing the strength.

Write a script to return the sum of the powers of all possible combinations; power is defined as the square of the largest number in a sequence, multiplied by the smallest.

##### Example 1

```
Input: @nums = (2, 1, 4)
Output: 141
Group 1: (2) => square(max(2)) * min(2) => 4 * 2 => 8
Group 2: (1) => square(max(1)) * min(1) => 1 * 1 => 1
Group 3: (4) => square(max(4)) * min(4) => 16 * 4 => 64
Group 4: (2,1) => square(max(2,1)) * min(2,1) => 4 * 1 => 4
Group 5: (2,4) => square(max(2,4)) * min(2,4) => 16 * 2 => 32
Group 6: (1,4) => square(max(1,4)) * min(1,4) => 16 * 1 => 16
Group 7: (2,1,4) => square(max(2,1,4)) * min(2,1,4) => 16 * 1 => 16
Sum: 8 + 1 + 64 + 4 + 32 + 16 + 16 => 141
```

This time we can do a one-liner.

```
@*ARGS.combinations(1..@*ARGS.elems).map({$_.max**2*$_.min}).sum.say
```

First we get all the combinations of the command-line input from single elements to the
entire thing with `@*ARGS.combinations(1..@*ARGS.elems)`

. Then with `.map()`

we take each combination and multiply the square (`**2`

) of the largest (`.max()`

) element of
the group and multiply it by the smallest (`.min()`

) element. All these values are
added together with `.sum()`

and the result is printed with `.say()`

.

For Perl we need to supply our own functions to replace the missing `.combinations()`

and `.sum()`

atleast which I did from code written for previous challenges. We need
`.min()`

and `.max()`

too but rather than code direct replacements for them, I wrote
a function called power that does the entire calculation mentioned in the spec.

```
sub power {
```

It takes an array reference as a parameter.

```
my ($arr) = @_;
```

The array is sorted numerically.

```
my @sorted = sort { $a <=> $b } @{$arr};
```

Now the maximum value will be the last element in the sorted array and the minimum value will be the first; we can plug them directly into the power formula.

```
return $sorted[-1] ** 2 * $sorted[0];
}
```

In the main code, we first define a variable to hold a running total.

```
my $total = 0;
```

Because my version of `combinations()`

cannot accept a range, we use a for
loop to get all the combinations of one element upto all the elements of `@nums`

.

```
for my $i (1 .. scalar @nums) {
```

Then for each of the combinations of `@nums`

of a particular length, we get
the `power()`

using `map()`

. We add all these powers together using `sum()`

and add that number to the running total.

```
$total += sum([ map { power($_) } combinations(\@nums, $i) ]);
}
```

Finally, we print the total.

```
say $total;
```