Peter’s blog ✴ Week 309 ✴ 17 February 2025

THE WEEKLY CHALLENGE
Mind the gap

The Perl Camel

Task 1

Min gap

You are given an array of integers, @ints, increasing order. Write a script to return the element before which you find the smallest gap.

Examples


Example 1
Input: @ints = (2, 8, 10, 11, 15)
Output: 11
 8 - 2  => 6
10 - 8  => 2
11 - 10 => 1
15 - 11 => 4
11 is where we found the min gap.

Example 2
Input: @ints = (1, 5, 6, 7, 14)
Output: 6
 5 - 1 => 4
 6 - 5 => 1
 7 - 6 => 1
14 - 7 => 7
6 and 7 where we found the min gap, so we pick the 
   first instance.

Example 3
Input: @ints = (8, 20, 25, 28)
Output: 28
 8 - 20 => 14
25 - 20 => 5
28 - 25 => 3
28 is where we found the min gap.

Analysis

So, once again, someone will have a nice one-liner and I have chosen to do it the more explicit way, by moving along @ints from the second element to the last, comparing each element with the previous one. While that might be expressed more succinctly in code, I don't think there is much one could do to optimise the search.

It's interesting that when I generate an @ints as 12 random integers in the range 0 - 999, the minimum gap is often 0 or 1 and rarely more than 9. If they were distributed evenly, the 11 gaps would all be 90.

Perl Weekly’s review

from PW issue 709

A complete solution that anyone can understand and follow. Bonus, you get DIY tool to try as well.

This review may cover either or both challenges for this week.

Try it 

Try running the script with any input:



example: 1, 4, 9, 34, 36

Script


#!/usr/bin/perl

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

use v5.26;    # The Weekly Challenge - 2025-02-17
use utf8;     # Week 309 - task 1 - Min gap
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';

min_gap(2, 8, 10, 11, 15);
min_gap(1, 5, 6, 7, 14);
min_gap(8, 20, 25, 28);

my @ints;
push @ints, int(rand(1000)) for 0 .. 11;
@ints = sort {$a <=> $b} @ints;
min_gap(@ints);

sub min_gap {
    
    my (@ints, $min_gap, $gap, $j, $before);
    
    # initialise
    @ints = @_; 
    $min_gap = 1e9;
    
    # loop over @ints starting at the second element
    for $j (1 .. $#ints) {
        $gap = $ints[$j] - $ints[$j - 1];
        next if $gap >= $min_gap;
        
        # found the smallest so far
        $min_gap = $gap;
        $before = $ints[$j];
    }
    
    say qq[\nInput:  \@ints = (] . join(', ', @ints) . ')';
    say qq[Output: minimum gap ($min_gap) is before $before];
}

11 lines of code

Output from script


Input:  @ints = (2, 8, 10, 11, 15)
Output: minimum gap (1) is before 11

Input:  @ints = (1, 5, 6, 7, 14)
Output: minimum gap (1) is before 6

Input:  @ints = (8, 20, 25, 28)
Output: minimum gap (3) is before 28

Input:  @ints = (9, 81, 354, 521, 599, 657, 674, 714, 734, 777, 805,
   976)
Output: minimum gap (17) is before 674

 

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