### Perl Weekly Challenge: Week 157

#### Challenge 1:

Pythagorean Means

You are given a set of integers.

Write a script to compute all three `Pythagorean Means` i.e Arithmetic Mean, Geometric Mean and Harmonic Mean of the given set of integers. Please refer to wikipedia page for more informations.

##### Example 1:
``````Input: @n = (1,3,5,6,9)
Output: AM = 4.8, GM = 3.8, HM = 2.8
``````
##### Example 2:
``````Input: @n = (2,4,6,8,10)
Output: AM = 6.0, GM = 5.2, HM = 4.4
``````
##### Example 3:
``````Input: @n = (1,2,3,4,5)
Output: AM = 3.0, GM = 2.6, HM = 2.2
``````

All I needed to do for this problem was to translate the formulas given in the Wikipedia article into Raku and Perl. So there isn't really much to say about the code.

``````my \$am = ([+] @n) / @n.elems;
``````

Well ok one thing; From the examples it would seem that we only should output one decimal digit of precision. `.round()` takes care of that.

``````my \$gm = ((([*] @n).abs) ** (-1 / -@n.elems)).round(0.1);
my \$hm = (@n.elems / ([+]  @n.map({ 1 / \$_; }))).round(0.1);

say "AM = \$am, GM = \$gm, HM = \$hm";
``````

(Full code on Github.)

For Perl, I used `nearest()` from `Math::Round` to do the rounding. I also reused `sum()` and `product()` from previous challenges to deal with the lack of `[+]` and `[*]`.

``````my \$am = sum(\@n) / scalar @n;
my \$gm = nearest(0.1, (abs product(\@n)) ** (-1 / scalar -@n));
my \$hm = nearest(0.1, scalar @n / sum([map { 1 / \$_; } @n]));

say "AM = \$am, GM = \$gm, HM = \$hm";
``````

(Full code on Github.)

#### Challenge 2:

Brazilian Number

You are given a number `\$n > 3`.

Write a script to find out if the given number is a `Brazilian Number`.

A positive integer number N has at least one natural number B where 1 < B < N-1 where the representation of N in base B has same digits.

##### Example 1:
``````Input: \$n = 7
Output: 1

Since 7 in base 2 is 111.
``````
##### Example 2:
``````Input: \$n = 6
Output: 0

Since 6 in base 2 is 110,
6 in base 3 is 20 and
6 in base 4 is 12.
``````
##### Example 3:
``````Input: \$n = 8
Output: 1

Since 8 in base 3 is 22.
``````

This was another easy one for Raku:

``````for 2 ..^ \$n - 1 -> \$B {
my @digits = \$n.base(\$B).comb;
``````

If all the digits are the same as the first one, we print 1 and finish the script.

``````    if @digits.all == @digits[0] {
say 1;
exit;
}
}
``````

If we've gone through the full range of bases, `\$n` is not a Brazilian number so we print 0.

``````say 0;
``````

(Full code on Github.)

Perl required a replacement for `.base()`. Luckily I had written such a thing way back in Challenge 43. That function returned a string so I had to make a slight modification to make it return a number. As it has been a long time, here it is:

``````sub base {
my (\$number, \$base) = @_;
my @digits = (0 .. 9, 'A' .. 'Z');
my @result;
while (\$number > (\$base - 1)) {
my \$digit = \$number % \$base;
push @result, \$digits[\$digit];
\$number /=  \$base;
}
push @result, \$digits[\$number];

return 0 + (join '', reverse @result);
}
``````

Back to the main part of the script...

``````my \$n = shift // die "Need an integer.\n";

for my \$B (2 .. \$n - 2) {
my @digits = split //, base(\$n, \$B);
``````

As a workaround for no `.all()`, I grepped for a digit that was not the same as the first digit.

``````    if (!grep { \$_ != \$digits[0] } @digits) {
say 1;
exit;
}
}

say 0;
``````

(Full code on Github.)