Peter’s blog ✴ Week 345 ✴ 27 October 2025

THE WEEKLY CHALLENGE
Peak at the answers

The Perl Camel

Task 1

Peak positions

You are given an array of integers, @ints. Find all the peaks in the array, a peak is an element that is strictly greater than its left and right neighbours. Return the indices of all such peak positions.

Examples


Example 1
Input: @ints = (1, 3, 2)
Output: (1)

Example 2
Input: @ints = (2, 4, 6, 5, 3)
Output: (2)

Example 3
Input: @ints = (1, 2, 3, 2, 4, 1)
Output: (2, 4)

Example 4
Input: @ints = (5, 3, 1)
Output: (0)

Example 5
Input: @ints = (1, 5, 1, 5, 1, 5, 1)
Output: (1, 3, 5)

Analysis

I can't think of a better way than simply looping over the elements of @ints from the second to the second last one, pushing the index onto @peaks if the current element exceeds both neighbours.

Clearly there need to be at least 3 elements in @ints, so I check for that and return an empty @peaks if there aren't enough.

The algorithm works for integers less, greater or equal to zero, and - although not required - for non-integers too.

Perl Weekly’s review

from PW issue 745

A simple, effective and useful Perl implementation that uses little code to accurately address both issues. Without superfluous abstraction or flourish, Peter concentrates on the fundamental algorithmic requirements. It is an example of "get the job done" programming.

Try it 

Try running the script with any input:



example: 3, 14, 1, 59, 26, 5, 35

Script


#!/usr/bin/perl

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

use v5.26;    # The Weekly Challenge - 2025-10-27
use utf8;     # Week 345 - task 1 - Peak positions
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';
use Encode;

peak_positions(1, 2, 3, 2, 1);
peak_positions(1, 2, 3, 4, 5);
peak_positions(3, 3, 3, 3, 3);
peak_positions(3, 2, 1, 2, 3);
peak_positions(1, 2, 1, 3, 1, 4, 1, 6, 1);
peak_positions(1, 2);
peak_positions(-3, -2, -4, 0, 9, -100);

sub peak_positions {
    
    my (@ints, @peaks, $j);
    
    # initialise
    @ints = @_;
    
    # do as instructed
    if ($#ints > 2) {
        for $j (1 .. $#ints - 1) {
            push @peaks, $j if ($ints[$j] > $ints[$j - 1]
                and $ints[$j] > $ints[$j + 1]);
        }
    }
        
    say qq[\nInput:  (] . join(', ', @ints) . ')';
    say qq[Output: (] . join(', ', @peaks) . ')';
}

9 lines of code

Output from script


Input:  (1, 2, 3, 2, 1)
Output: (2)

Input:  (1, 2, 3, 4, 5)
Output: ()

Input:  (3, 3, 3, 3, 3)
Output: ()

Input:  (3, 2, 1, 2, 3)
Output: ()

Input:  (1, 2, 1, 3, 1, 4, 1, 6, 1)
Output: (1, 3, 5, 7)

Input:  (1, 2)
Output: ()

Input:  (-3, -2, -4, 0, 9, -100)
Output: (1, 4)

 

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