I’ve been doing the Weekly
Challenges. The
latest
involved a variety of means and more number theory. (Note that this is
open until 27 March 2022.)
Task 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.
I ended up breaking this down into lots of separate functions. Each
mean can be calculated on a reduce
-like principle, but they have
quite different functions inside them, so each one happens separately
(particularly since if I ever need to to this in the real world I'll
probably want only one of those means); then the unstated rounding to
one decimal place is its own function again.
As for "reduce" itself, the idea of repeatedly applying a function to
members of a list, the only languages I'm using that don't have
something like it either built-in (most of them) or in a core module
(Perl, via List::Util
) are PostScript and Lua. And by coincidence,
just before this came out, I'd been working on my iterables
library
for PostScript…
Some of the languages have built-in sum
and even product
functions
which might be faster for large lists, but it seemed cleaner to lay
everything out explicitly.
The overall function being tested: calculate, round and return all the
means as a hashmap. Kotlin:
fun pythagoreanmeans(s: List<Int>): Map<String,Double> {
return hashMapOf(
"AM" to round1(arithmeticmean(s)),
"GM" to round1(geometricmean(s)),
"HM" to round1(harmonicmean(s))
)
}
Round to one decimal place. (Raku, Python and Ruby have built-ins to
do this.)
fun round1(x: Double): Double {
return floor(10.0*x+0.5)/10.0;
}
The arithmetic mean: take the sum of the list values, divide by the length.
fun arithmeticmean(s: List<Int>): Double {
return s.reduce { acc, x -> acc + x }.toDouble() / s.size
}
The geometric mean: take the product of the list values, exponentiate
to (1/length).
fun geometricmean(s: List<Int>): Double {
return s.reduce { acc, x -> acc * x }.toDouble().pow(1.0/s.size)
}
The harmonic mean: take the reciprocal of each entry, sum them, and
divide into the length. (In some languages I initialised the reduce
accumulator with 0 and added 1/x
rather than inverting the whole
series first.)
fun harmonicmean(s: List<Int>): Double {
return s.size/(s.map {1.0/it}.reduce { acc, x -> acc + x })
}
Task 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.
Which for me breaks down to: for each possible number base (from 2 up
to n-2), calculate the digits of the conversion into that base until
one of them differs from the first one. Raku:
sub brazilian($n) {
Loop over number bases:
for (2..$n-2) -> $b {
Set up the working copy of the parameter, the boolean value for
whether a valid Brazilian form has been found, and the first digit.
my $nn = $n;
my $braz = True;
my $digit = $nn % $b;
while ($nn > 0) {
Compare the next digit with the one we've already established. If it's
the same, continue. (This is slightly inefficient as we end up doing
the first modulus twice, but I thought the code was cleaner.)
if ($digit == $nn % $b) {
$nn div= $b;
} else {
Otherwise, this isn't a Brazilian form and we can stop here.
$braz = False;
last;
}
}
If we found a Brazilian form, return it; we don't need to look for more.
if ($braz) {
return True;
}
}
If we tried all the bases, it's not a Brazilian number.
return False;
}
Full code on
github.
Comments on this post are now closed. If you have particular grounds for adding a late comment, comment on a more recent post quoting the URL of this one.