Peter
Peter Campbell Smith

A middling deal

Weekly challenge 291 — 14 October 2024

Week 291: 14 Oct 2024

Task 1

Task — Middle index

You are given an array of integers, @ints. Write a script to find the leftmost middle index (MI), ie the smallest amongst all the possible ones. A middle index is an index where:

ints[0] + ints[1] + … + ints[MI-1] == 
   ints[MI+1] + ints[MI+2] + … + ints[ints.length-1]

If MI == 0, the left side sum is considered to be 0. Similarly, if
MI == ints.length - 1, the right side sum is considered to be 0.

Return the leftmost MI that satisfies the condition, or -1 if there is no such index.

Examples


Example 1
Input: @ints = (2, 3, -1, 8, 4)
Output: 3
The sum of the numbers before index 3 is: 2 + 3 + -1 = 4
The sum of the numbers after index 3 is: 4 = 4

Example 2
Input: @ints = (1, -1, 4)
Output: 2
The sum of the numbers before index 2 is: 1 + -1 = 0
The sum of the numbers after index 2 is: 0

Example 3
Input: @ints = (2, 5)
Output: -1
There is no valid MI.

Analysis

My solution consists of maintaining two pots, $before, initially zero, and $after, initially equal to the sum of all the values in @ints.

I then, for $i (0 .. scalar(@ints) - 1):

  • subtract $ints[$i] from $after
  • if $before == $after then this is an MI, so report and stop.
  • Or else add $ints[$i] to $before and continue

... and if no MI has been found then there isn't one.

I don't know what this says about my thought processes or my ability to write correct code, but I think this is the first challenge for which my code compiled and ran correctly for all the normal and edge cases, at the very first attempt!

Try it 

Try running the script with any input:



example: 5, 6, 11, 1, 10

Script


#!/usr/bin/perl

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

use v5.26;    # The Weekly Challenge - 2024-10-14
use utf8;     # Week 291 - task 1 - Middle index
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';

middle_index(2, 3, -1, 8, 4);
middle_index(0, 3, 4, -7);
middle_index(3, 4, -7, 0);
middle_index(1, 2, 3, 4, 5);
middle_index(9, 9, 9, 9, 9);

sub middle_index {
    
    my (@ints, $before, $after, $i);
    
    @ints = @_;
    say qq[\nInput:  \@ints = (] . join(', ', @ints) . ')';
    
    # initialise
    $before = 0;
    $after += $_ for @ints;
    
    # loop over elements of @ints to find first MI
    for $i (0 .. scalar @ints - 1) {
        
        # remove $ints[$i] from $after
        $after -= $ints[$i];
        
        # do we have an MI?
        if ($before == $after) {
            say qq[Output: $i];
            return;
        }
        
        # add $ints[$i] to before, and try the next $i
        $before += $ints[$i];
    }
    
    # no MI found
    say qq[Output: -1];
}

Output


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

Input:  @ints = (0, 3, 4, -7)
Output: 0

Input:  @ints = (3, 4, -7, 0)
Output: 3

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

Input:  @ints = (9, 9, 9, 9, 9)
Output: 2

 

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