skip to Main Content

I’m trying to build a function that returns the index of an array where equal sides of the array sum to the same value.

I can get all tests to pass apart from this one:
$this->assertSame(6,find_even_index([10,-80,10,10,15,35,20]));

I don’t understand why this test has been added by Codewars when it doesn’t seem correct? Index 6 is the last item, and doesn’t have a right side to equate.

Challenge was taken from Codewars:
https://www.codewars.com/kata/5679aa472b8f57fb8c000047/solutions/php

Code:

$numbers = [10,-80,10,10,15,35,20];

echo getEqualSidesIndex($numbers) . PHP_EOL;

function getEqualSidesIndex(array $numbers) : int {
    foreach ($numbers as $key => $value) {
        if ($key < 1) {
            continue; 
        }
    
        $itemsBeforeCurrent = array_slice($numbers, 0, $key - 1);
        $itemsAfterCurrent = array_slice($numbers, $key, count($numbers) - 1);

        if (array_sum($itemsBeforeCurrent) == array_sum($itemsAfterCurrent)) {
            return $key - 1;
        }
    }

    return -1;
}

Tests:

class FindEvenIndexTest extends TestCase
{
    public function testIt() {
      $this->assertSame(3,find_even_index(array(1,2,3,4,3,2,1)));
      $this->assertSame(1,find_even_index([1,100,50,-51,1,1]));
      $this->assertSame(-1,find_even_index([1,2,3,4,5,6]));
      $this->assertSame(3,find_even_index([20,10,30,10,10,15,35]));
      $this->assertSame(0,find_even_index([20,10,-80,10,10,15,35]));
      $this->assertSame(6,find_even_index([10,-80,10,10,15,35,20]));
      $this->assertSame(-1,find_even_index(range(1,100)));
      $this->assertSame(0,find_even_index([0,0,0,0,0]),"Should pick the first index if more cases are valid");
      $this->assertSame(3,find_even_index([-1,-2,-3,-4,-3,-2,-1]));
      $this->assertSame(-1,find_even_index(range(-100,-1)));

    }
}

Instructions:

You are going to be given an array of integers. Your job is to take
that array and find an index N where the sum of the integers to the
left of N is equal to the sum of the integers to the right of N. If
there is no index that would make this happen, return -1.

For example:

Let’s say you are given the array {1,2,3,4,3,2,1}: Your function will
return the index 3, because at the 3rd position of the array, the sum
of left side of the index ({1,2,3}) and the sum of the right side of
the index ({3,2,1}) both equal 6.

Let’s look at another one. You are given the array {1,100,50,-51,1,1}:
Your function will return the index 1, because at the 1st position of
the array, the sum of left side of the index ({1}) and the sum of the
right side of the index ({50,-51,1,1}) both equal 1.

Last one: You are given the array {20,10,-80,10,10,15,35} At index 0
the left side is {} The right side is {10,-80,10,10,15,35} They both
are equal to 0 when added. (Empty arrays are equal to 0 in this
problem) Index 0 is the place where the left side and right side are
equal.

Note: Please remember that in most programming/scripting languages the
index of an array starts at 0.

Input: An integer array of length 0 < arr < 1000. The numbers in the
array can be any integer positive or negative.

Output: The lowest index N where the side to the left of N is equal to
the side to the right of N. If you do not find an index that fits
these rules, then you will return -1.

Note: If you are given an array with multiple answers, return the
lowest correct index.

2

Answers


  1. You’re right, the test case $this->assertSame(6,find_even_index([10,-80,10,10,15,35,20])); is wrong. The index 6 is the last item in the array, so there is no right side to compare it to.

    This code works by first checking that the index is greater than 0. If it is not, then the function continues to the next iteration.

    Next, the function calculates the sum of the elements to the left of the current index and the sum of the elements to the right of the current index. If the two sums are equal, then the function returns the current index.

    However, if the current index is equal to the last element in the array, then there is no right side to compare it to. In this case, the function returns -1.

    The code also works correctly for the test case that you mentioned. The index 6 is the last element in the array, so the function returns -1.

    <?php
    
    function getEqualSidesIndex(array $numbers) : int {
        foreach ($numbers as $key => $value) {
            if ($key < 1) {
                continue; 
            }
    
            $left_sum = array_sum(array_slice($numbers, 0, $key - 1));
            $right_sum = array_sum(array_slice($numbers, $key + 1));
    
            if ($left_sum == $right_sum) {
                if ($key == count($numbers) - 1) {
                    // The last element in the array doesn't have a right side, so return -1
                    return -1;
                } else {
                    return $key - 1;
                }
            }
        }
    
        return -1;
    }
    
    $numbers = [10,-80,10,10,15,35,20];
    
    echo getEqualSidesIndex($numbers) . PHP_EOL;
    
    Login or Signup to reply.
  2. If you consider another test for comparison, [20,10,-80,10,10,15,35] should give 0. But if you apply the logic

    Index 6 is the last item, and doesn’t have a right side to equate.

    Then the 0th item does not have a left side, so how can you match this. The way it does match is that the left is considered to be 0, so in the example you say is incorrect – it is expecting all of the previous values to match the ‘0’ on the right hand side.

    This function rather than adding up all the values repeatedly, it keeps track of the left and right sums, adjusting them at each item. This should perform a lot better…

    function getEqualSidesIndex(array $numbers) : int
    {
        // Start with the first number 
        $left = $numbers[0];
        // Start with the all the remaining values minus the first 
        $right = array_sum($numbers) - $left;
        // If the remaining values match 0, then the match is the first item
        if ($right === 0)    {
            return 0;
        }
        // Go from the second value
        foreach (array_slice($numbers, 1) as $key => $value) {
            // Take the new value to be considered away from the remaining sum
            $right -= $value;
            // Check for a match
            if ($left == $right) {
                return $key + 1;
            }
            // Add the value to the new left sum and continue.
            $left += $value;
        }
    
        return -1;
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search