# Perl Weekly Challenge 157.

My solutions (task 1 and task 2 ) to the The Weekly Challenge - 157.

``````Submitted by: Mohammad S Anwar
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
informations.

Example 1:
Input: @n = (1,3,5,6,9)
Output: AM = 4.8, GM = 3.9, 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
``````

I just apply the definitions. The arithmetic mean of a sequence of N numbers is their sum divided by N, their geometric mean is the N-th root of their product, and their harmonic mean is the inverse of the arithmetic mean of their inverses. That yields a simple oneliner. .

``````perl -MList::Util=sum0,product -E 'say "In: ", join ", ", @ARGV; say sprintf
"AM=%.2f GM=%.2f HM=%.2f", sum0(@ARGV)/@ARGV, product(@ARGV)**(1/@ARGV),
@ARGV/sum0(map {1/\$_} (@ARGV));
' 1 3 5 6 9

perl -MList::Util=sum0,product -E 'say "In: ", join ", ", @ARGV;
say sprintf "AM=%.2f GM=%.2f HM=%.2f", sum0(@ARGV)/@ARGV, product(@ARGV)**(1/@ARGV),
@ARGV/sum0(map {1/\$_} (@ARGV));
' 2 4 6 8 10

perl -MList::Util=sum0,product -E 'say "In: ", join ", ", @ARGV;
say sprintf "AM=%.2f GM=%.2f HM=%.2f", sum0(@ARGV)/@ARGV, product(@ARGV)**(1/@ARGV),
@ARGV/sum0(map {1/\$_} (@ARGV));
' 1 2 3 4 5
``````

Results:

``````In: 1, 3, 5, 6, 9
AM=4.80 GM=3.82 HM=2.76
In: 2, 4, 6, 8, 10
AM=6.00 GM=5.21 HM=4.38
In: 1, 2, 3, 4, 5
AM=3.00 GM=2.61 HM=2.19
``````

My first geometric mean disagrees in the first example with that in the problem statement; I guess it is a typo.

The full version is almost identical. I add a few checks.

`````` 1  # Perl weekly challenge 157
2  # Task 1: Pythagorean means
3  #
5  use v5.12;
6  use warnings;
7  use List::Util qw(sum0 product any);
8  die "Usage: ./ch-1.pl N1 N2 N3 ... to get the means of the numbers Ni..." unless @ARGV;
9  say "In: ", join ", ", @ARGV;
10  my \$AM= sprintf "%.2f", sum0(@ARGV)/@ARGV;            # arithmetic mean
11  my \$product=product(@ARGV);
12  my \$GM=(\$product<0 && @ARGV%2==0)? "Undefined":sprintf "%.2f", \$product**(1/@ARGV);
13  my \$HM=(any{\$_==0} (@ARGV))?"Undefined":sprintf "%.2f", @ARGV/sum0(map {1/\$_} (@ARGV));
14  say sprintf "AM=\$AM GM=\$GM HM=\$HM";
``````

Examples:

``````./ch-1.pl 1 3 5 6 9
./ch-1.pl 2 4 6 8 10
./ch-1.pl 1 2 3 4 5
``````

Results:

``````In: 1, 3, 5, 6, 9
AM=4.80 GM=3.82 HM=2.76
In: 2, 4, 6, 8, 10
AM=6.00 GM=5.21 HM=4.38
In: 1, 2, 3, 4, 5
AM=3.00 GM=2.61 HM=2.19
``````

Examples with errors:

``````./ch-1.pl 0 1 2 3
./ch-1.pl 1 2 3 -4
``````

Results:

``````In: 0, 1, 2, 3
AM=1.50 GM=0.00 HM=Undefined
In: 1, 2, 3, -4
AM=0.50 GM=Undefined HM=2.53
``````

``````Submitted by: Mohammad S Anwar
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 30 and
6 in base 4 is 12.
Example 3:
Input: \$n = 8
Output: 1

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

A Brazilian number in base B with M repeated digits D is of the form N=DDDD..DDD=D BM-1 + D BM-2+…+D B1+D B0=D(BM-1)/(B-1) after factorizing D and simplifying the geometric sum. As the largest value of D is B-1, N is smaller than BM. Thus, for a given base, B, I can find M as the smallest integer larger than log(N)/log(B). From M, I can obtain D=N*(B-1)/(D**{M}-1). Therefore, a number N is Brazilian if for some base between 2 and N-2, the number D obtained above is an integer. This yields the simple one liner:

``````perl -MPOSIX=ceil,floor -E 'N:for \$n(@ARGV){for \$b(2..\$n-2){\$m=ceil(log(\$n)/log(\$b));
\$d=floor(\$n*(\$b-1)/(\$b**\$m-1)); say("\$n=", ((\$d)x\$m)," in base \$b is Brazilian"), next N
if \$d*(\$b**\$m-1)/(\$b-1)==\$n} say "\$n is not Brazilian"} ' `seq 30`
``````

Results:

``````1 is not Brazilian
2 is not Brazilian
3 is not Brazilian
4 is not Brazilian
5 is not Brazilian
6 is not Brazilian
7=111 in base 2 is Brazilian
8=22 in base 3 is Brazilian
9 is not Brazilian
10=22 in base 4 is Brazilian
11 is not Brazilian
12=22 in base 5 is Brazilian
13=111 in base 3 is Brazilian
14=22 in base 6 is Brazilian
15=1111 in base 2 is Brazilian
16=22 in base 7 is Brazilian
17 is not Brazilian
18=33 in base 5 is Brazilian
19 is not Brazilian
20=22 in base 9 is Brazilian
21=111 in base 4 is Brazilian
22=22 in base 10 is Brazilian
23 is not Brazilian
24=44 in base 5 is Brazilian
25 is not Brazilian
26=222 in base 3 is Brazilian
27=33 in base 8 is Brazilian
28=44 in base 6 is Brazilian
29 is not Brazilian
30=33 in base 9 is Brazilian
``````

The full code is:

`````` 1  # Perl weekly challenge 157
2  # Task 2: Brazilian number
3  #
5  use v5.12;
6  use warnings;
7  use POSIX qw(ceil floor);
8  N:
9      for my \$n(@ARGV){
10  	for my \$b(2..\$n-2){
11  	    my \$m=ceil(log(\$n)/log(\$b));
12  	    my \$d=floor(\$n*(\$b-1)/(\$b**\$m-1));
13  	    say("\$n=", ((\$d)x\$m)," in base \$b is Brazilian"), next N
14  		if \$d*(\$b**\$m-1)/(\$b-1)==\$n
15  	}
16  	say "\$n is not Brazilian"
17  }

./ch-2.pl `seq 30`
``````

Results:

``````1 is not Brazilian
2 is not Brazilian
3 is not Brazilian
4 is not Brazilian
5 is not Brazilian
6 is not Brazilian
7=111 in base 2 is Brazilian
8=22 in base 3 is Brazilian
9 is not Brazilian
10=22 in base 4 is Brazilian
11 is not Brazilian
12=22 in base 5 is Brazilian
13=111 in base 3 is Brazilian
14=22 in base 6 is Brazilian
15=1111 in base 2 is Brazilian
16=22 in base 7 is Brazilian
17 is not Brazilian
18=33 in base 5 is Brazilian
19 is not Brazilian
20=22 in base 9 is Brazilian
21=111 in base 4 is Brazilian
22=22 in base 10 is Brazilian
23 is not Brazilian
24=44 in base 5 is Brazilian
25 is not Brazilian
26=222 in base 3 is Brazilian
27=33 in base 8 is Brazilian
28=44 in base 6 is Brazilian
29 is not Brazilian
30=33 in base 9 is Brazilian
``````
Written on March 21, 2022