Peter
Peter Campbell Smith

Mean Brazilians

Weekly challenge 157 — 21 March 2022

Week 157 - 21 Mar 2022

Task 1

Task — Pythagorean means

You are given a set of integers.

Write a script to compute all three Pythagorean Means ie Arithmetic Mean, Geometric Mean and Harmonic Mean of the given set of integers. Please refer to Wikipedia page for more information.

Examples


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

Analysis

I'm never quite sure what is wanted or considered good in these tasks. The options seem to be:

  1. There's a module to do this
  2. I can do this in one somewhat inscrutable line
  3. I can do this in a readable way with lots of comments

If we're aiming to save coder time and not reinventing the wheel, then option 1 is clearly correct. I would almost always use that in a production environment.

Option 2 gives people a chance to demonstrate how compact - and maybe fast - Perl can be, which is a valid aim. If the code is never going to be changed then it's fine, but I suspect that whoever has to come along later and maintain it - even if that's you - is going to scratch their heads for a while.

Option 3 is the way to go if you're trying to write easily maintainable code. It may not be the fastest solution - although often it is easily fast enough.

So for this task I went squarely for option 3: code it just as it's explained in Wikipedia, ie take the list elements one at a time and produce a running sum, product and sum of reciprocals.

Try it 

Try running the script with any input:



example: 3, 1, 4, 1, 5, 9

Script


#!/usr/bin/perl

# Peter Campbell Smith - 2022-03-22
# PWC 157 task 1

use v5.28;
use strict;
use warnings;
use utf8;

my ($sum, $n, $product, $reciprocals, @examples, $example, $string);

# given sets of integers
@examples = ([1, 3, 5, 6, 9], [2, 4, 6, 8, 10], [1, 2, 3, 4, 5], [73, 201, 1, 99, 123, 14, 83, 46, 77]);

# loop over sets
for $example (@examples) {
    
    # get started
    $product = 1;
    $sum = $reciprocals = 0;
    $string = '';
    
    # form sum, product and sum of reciprocals
    for $n (@$example) {
        $sum += $n;
        $product *= $n;
        $reciprocals += 1 / $n;
        $string .= qq[$n, ];
    }
    
    # and tell the world
    say qq[\nInput:  \@n = (] . substr($string, 0, -2) . qq[)\nOutput: ] .
        qq[AM = ] .   sprintf('%1.1f', ($sum / scalar @$example)) .
        qq[, GM = ] . sprintf('%1.1f', ($product ** (1 / scalar @$example))) .
        qq[, HM = ] . sprintf('%1.1f', (scalar @$example / $reciprocals));
}

Output


Input:  @n = (1, 3, 5, 6, 9)
Output: AM = 4.8, GM = 3.8, HM = 2.8

Input:  @n = (2, 4, 6, 8, 10)
Output: AM = 6.0, GM = 5.2, HM = 4.4

Input:  @n = (1, 2, 3, 4, 5)
Output: AM = 3.0, GM = 2.6, HM = 2.2

Input:  @n = (73, 201, 1, 99, 123, 14, 83, 46, 77)
Output: AM = 79.7, GM = 44.9, HM = 7.8