Peter’s blog ✴ Week 304 ✴ 13 January 2025

THE WEEKLY CHALLENGE
Adding ones and maxing the mean

The Perl Camel

Task 2

Maximum average

You are given an array of integers, @ints and an integer, $n which is less than or equal to total elements in the given array. Write a script to find the contiguous subarray whose length is the given integer, $n, and has the maximum average. It should return the average.

Examples


Example 1
Input: @ints = (1, 12, -5, -6, 50, 3), $n = 4
Output: 12.75
Subarray: (12, -5, -6, 50)
Average: (12 - 5 - 6 + 50) / 4 = 12.75

Example 2
Input: @ints = (5), $n = 1
Output: 5

Analysis

The easy way to do this is just to calculate the average of all the possible subarrays, of which there will only be length(@ints) - $n + 2. Even if @ints contains 10 000 integers this takes less than a second.

So that's what I am submitting.

Perl Weekly’s review

from PW issue 704

Nice hack to make the task easier. DIY tool lets you play with it too.

Try it 

Try running the script with any input:



example: 1, 99, -43, 78, 20, 71, -40



example: 4

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

use v5.26;    # The Weekly Challenge - 2025-01-13
use utf8;     # Week 304 - task 2 - Maximum average
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';

maximum_average([1, 12, -5, -6, 50, 3], 4);
maximum_average([5, 5, 5, 5, 0, 0, 0], 4);
maximum_average([0, 0, 0, 0, 0, 6, 6], 5);

my @ints;
push @ints, int(rand(100)) - 50 for 1 .. 100;
maximum_average(\@ints, 10);

sub maximum_average {
    
    my (@ints, $n, $max_average, $max_suum, $start, $sum, $average, $subarray);
    
    # initialise
    @ints = @{$_[0]};
    $n = $_[1];
    $max_average = 0;
    
    # loop over staring points
    for $start (0 .. $#ints - $n + 1) {
        $sum = 0;
        $sum += $_ for @ints[$start .. $start + $n - 1];
        $average = $sum / $n;
        
        # potential answer
        if ($average > $max_average) {
            $max_average = $average;
            $subarray = join(', ', @ints[$start .. $start + $n - 1]);
        }
    }
    
    # report
    say qq[\nInput:  \@ints = (] . join(', ', @ints) . qq[), \$n = $n];
    say qq[Output: $max_average - ($subarray)];
}

14 lines of code

Output from script



Input:  @ints = (1, 12, -5, -6, 50, 3), $n = 4
Output: 12.75 - (12, -5, -6, 50)

Input:  @ints = (5, 5, 5, 5, 0, 0, 0), $n = 4
Output: 5 - (5, 5, 5, 5)

Input:  @ints = (0, 0, 0, 0, 0, 6, 6), $n = 5
Output: 2.4 - (0, 0, 0, 6, 6)

Input:  @ints = (26, -4, 24, -28, -1, -7, 4, -35, -5,
-6, -37, 22, 14, 2, -37, -25, -26, 23, 6, -13, 40, -10,
12, 21, 38, 3, 43, 1, -34, 18, 21, 25, 2, -16, 44, -22,
-33, -50, 28, -9, -40, 29, 43, -32, -3, -9, 1, -7, 5,
-27, -28, 3, -19, -24, -17, 10, -42, -31, 21, 32, 17, -7,
-32, 18, -17, -13, -40, 0, 27, 22, 42, 18, -30, 37, 3,
-17, -14, 13, 28, -9, 13, 15, -12, 16, -37, -31, -38, 42,
39, 37, 2, 39, -32, -16, 19, -4, 18, 6, 6, 27), $n = 10
Output: 16.3 - (23, 6, -13, 40, -10, 12, 21, 38, 3, 43)

 

Any content of this website which has been created by Peter Campbell Smith is in the public domain