2

I'm trying to create a function that checks if two numbers within an array have a sum of zero.

[1,2,3,4,5] => false
[1,2,3,-2,5] => true

This is what I have so far but I can't figure it out:

def zero_sum?(arr)

  arr.each do |num|
    arr.each do |num2|
      if (num.to_i + num2.to_i) == 0
        true
      else
        false
      end
    end
  end

end
0

6 Answers 6

3

You want to know whether any combination of 2 elements adds up to zero. You can pretty much write that down verbatim:

arr.combination(2).any? {|a, b| (a + b).zero? }
Sign up to request clarification or add additional context in comments.

9 Comments

Gives different result for a list including a single zero. However, true to the English wording. I am torn.
@Amadan combination doesn't mix two array elements of the same index, which is why a single 0 yields false.
@mbratch: Yes, I know why. I'm just saying the OP has different expectations in his English and in his code. I followed code, Jörg followed words, and consequently we have different results. Only OP can say who is right. :)
The OP's code has wrong logic anyway (in handling true and false symmetrically), so it cannot be relied on. I also took the wording.
Understanding the methods provided by Enumerable is basic Ruby. In fact, it solves pretty much 80% of all basic programming problems.
|
2

You need return true instead of true.

This way, the value in the block is true when it needs to be, but the looping continues, and finally each returns arr.

Also, can be written shorter, but it is not as efficient:

def zero_sum?(arr)
  arr.product(arr).any? { |x, y| x + y == 0 }
end

A bit less nice but efficient:

def zero_sum?(arr)
  arr.product(arr) { |x, y| return true if x + y == 0 }
  false
end

1 Comment

To expand on the “efficiency” comments: both solutions are O(n²), however the practical time complexity of the second is, on average, half that of the first, and the memory complexity of the second is as little as 1/nth of the first.
1

an easy way to do it is:

def zero_sum?(arr)
  arr.count(0) > 1 or
  arr.-([0]).any?{|e| arr.include?(-e)}
end

1 Comment

I couldn't figure out what arr.-([]) was until I removed the dot and found it made no difference. As the parens are just to avoid ]., it's the same as (arr-[0]). You could also use arr.uniq, but that would be less descriptive.
1

another way to do this:-

array.product(array).any?{|arr| arr.sum.zero?}

Comments

0
arr.count(0) > 1 or 
  arr.uniq.map(&:abs).group_by(&:to_i).values.map(&:size).max > 0

I really don't think this is the best answer, but it might be of interest to someone. (Borrowed part before or from @sawa.)

Comments

0
arr.each_cons(2).select{|array|array.inject(:+) == 0}.count > 0

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.