The Weekly Challenge 351

Average Without Extremes & Progression Detection!

Original Challenge Link

Task 1: Special Average

"Trim the Extremes: What’s the Real Average?"

This week's first task asks us to compute an average after excluding the minimum and maximum values from the given array. If removing those extremes leaves no remaining values, the result should be 0, which also covers the case where every element is identical.

The Strategy: Find the minimum and maximum values first. If they are equal, everything is the same and the answer is immediately 0. Otherwise, remove all occurrences of the minimum and maximum, then compute the average of what remains. If nothing remains after filtering, return 0.
Perl Implementation
sub special_average ($ints) {
    ($ints) = $LIST_CHECK->($ints);
    return 0 unless @$ints;

    my $min = min(@$ints);
    my $max = max(@$ints);
    return 0 if $min == $max;

    my $min_count = grep { $_ == $min } @$ints;
    my $max_count = grep { $_ == $max } @$ints;

    my $remaining = @$ints - $min_count - $max_count;
    return 0 if $remaining <= 0;

    my $total = sum0(@$ints) - ( $min * $min_count ) - ( $max * $max_count );
    return $total / $remaining;
}
Python Implementation
def special_average(ints: Sequence[float]) -> float:
    """
    Return the average after removing all occurrences of the minimum and maximum.
    """
    if not ints:
        return 0.0

    min_val = min(ints)
    max_val = max(ints)

    if min_val == max_val:
        return 0.0

    remaining = [value for value in ints if value != min_val and value != max_val]
    if not remaining:
        return 0.0

    return sum(remaining) / len(remaining)

Task 2: Arithmetic Progression

"Can It Line Up? Testing for Equal Steps!"

The second task asks whether the given numbers can be rearranged into an arithmetic progression. A sequence is arithmetic if the difference between every pair of adjacent elements is constant.

The Strategy: Sort the numbers and compare the difference between consecutive values. Once sorted, any arithmetic progression must have the same gap everywhere. For floating-point values, use a tiny tolerance when comparing differences so harmless rounding issues do not produce false negatives.
Perl Implementation
sub can_form_arithmetic_progression ($nums) {
    ($nums) = $LIST_CHECK->($nums);
    return 1 if @$nums <= 2;

    my @sorted = sort { $a <=> $b } @$nums;
    my $diff   = $sorted[1] - $sorted[0];

    for my $i ( 2 .. $#sorted ) {
        my $current = $sorted[$i] - $sorted[ $i - 1 ];
        return 0 if abs( $current - $diff ) > EPSILON;
    }

    return 1;
}
Python Implementation
def can_form_arithmetic_progression(numbers: Sequence[float]) -> bool:
    """
    Return True if numbers can be reordered into an arithmetic progression.
    """
    if len(numbers) <= 2:
        return True

    sorted_numbers = sorted(numbers)
    common_diff = sorted_numbers[1] - sorted_numbers[0]

    for idx in range(2, len(sorted_numbers)):
        current = sorted_numbers[idx] - sorted_numbers[idx - 1]
        if not math.isclose(current, common_diff, rel_tol=1e-9, abs_tol=1e-9):
            return False
    return True