All_else method (Ruby)

Viewed 55

I'm trying to create a method that iterates through an array and add up all of its elements and returns the element that is half of its sum, else it will return nil.

Examples:

p all_else_equal([2, 4, 3, 10, 1]) #=> 10, because the sum of all elements is 20
p all_else_equal([6, 3, 5, -9, 1]) #=> 3, because the sum of all elements is 6
p all_else_equal([1, 2, 3, 4])     #=> nil, because the sum of all elements is 10 and there is no 5 in the array.

My solution was to iterate through the array and add each element together using a 'sum' variable. Then write a conditional statement stating if half of the sum is included in the arr, then return the element, else return nil. But for what ever reseason I keep getting 'nil'. Can anyone out there tell me why this is wrong? Here's my code:

def all_else_equal(arr)
  sum = 0
  sum_half = sum / 2  

  arr.each_with_index do |ele, i|
    sum += ele    

    if sum_half == ele
      return ele
    else
      return nil
    end
  end
end

console:

nil
3 Answers

so your code will return nil right after the first value. this is because the return condition is in the loop. to solve this, move it out as shown below. also, create the sum_half variable after the sum has already been evaluated:

def all_else_equal(arr)
  sum = 0

  arr.each_with_index do |ele, i|
    sum += ele    
  end

  sum_half = sum / 2  

  if arr.include?(sum_half) #check if sum_half in array
      return sum_half
  else
      return nil
  end
end

p all_else_equal([2, 4, 3, 10, 1]) #=> 10, because the sum of all elements is 20
p all_else_equal([6, 3, 5, -9, 1]) #=> 3, because the sum of all elements is 6
p all_else_equal([1, 2, 3, 4])     #=> nil, because the sum of all elements is 10 and there is no 5 in the array.

a simpler alternative:

def all_else_equal(arr)
  sum_half = arr.sum / 2  
  arr.include?(sum_half) ? sum_half : nil
end
p all_else_equal([2, 4, 3, 10, 1]) #=> 10, because the sum of all elements is 20
p all_else_equal([6, 3, 5, -9, 1]) #=> 3, because the sum of all elements is 6
p all_else_equal([1, 2, 3, 4])     #=> nil, because the sum of all elements is 10 and there is no 5 in the array.

I see a few things here. First, in Ruby and all imperative languages, variable assignments are evaluated only at their time of execution -- so your sum_half variable will always be equal to 0 / 2 or 0. It will not dynamically re-evaluate to always be equal to sum / 2. You would need to recompute it after every iteration of the loop for it to be accurate.

Second, from a logical perspective, your sum variable is only really the sum so far. Checking if half of it is equal to the current element is not what you want to do, because even if that's true, it doesn't mean the current element is half of the final sum. Instead, you might want to find the full sum, divide it in two, and then look for an element that matches that value.

Also, stylistically, your each_with_index is currently unnecessary because you're not using the index at all -- change it to just an each until you find a use for that index value.

@RobertNubel and @PhiAgent have great answers - I would suggest you especially work through PhiAgent's Answer.

I will only add a worked example for the first iteration of the loop so you can see exactly what is happeneing

A worked Example with Comments:

def all_else_equal(arr) ## let's say array = [1,2] is passed in as a parameter
  sum = 0              
  sum_half = sum / 2    ## => sum_half = 0

  arr.each_with_index do |ele, i|  # => elem = 1 (given the first element in the array)
    sum += ele         # => sum is now 1

    if sum_half == ele # => 0 == 1  ## this will be false
      return ele
    else
      return nil   # => nil be returned
    end
  end
end

@PhiAgent has a great solution to get the code working.

Related