Reputation: 3335
Is there anyway to iterate through different combinations of arrays?
I'm writing a program that returns true if the largest number in an array can be the sum of any of the members of the array.
This is my code: (forgive me, i learned how to program 2 weeks ago for the first time)
def ArrayAdditionI(arr)
arr=arr.sort
largest=arr.pop
n=arr.length
for i in 1..n
if arr.combination(i).to_a.any? {|array| array.inject(:+)==largest}
return true
else
return false
end
end
end
i tested it for a = [1,2,3,4] and it returned false even though clearly, 3+1 = 4. When I change the above code from arr.combination(i) to arr.combination(2) its returns true. So I'm guessing it has something to do with the combination method not being able to be looped. Any suggestions?
Upvotes: 1
Views: 287
Reputation: 110735
You have return false
in the wrong place. As it is, false
is returned is there is no combination of one element (i.e., one element other than the one you've removed after sorting) that sums (i.e., is equal to) largest
. Rather you want to return false
only if no combination of any size sums to largest
. This is what you need:
def max_match?(arr)
arr=arr.sort
largest=arr.pop
n=arr.length
for i in 1..n
return true if arr.combination(i).any? {|array|
array.inject(:+)==largest}
end
false
end
arr = [1,4,7,3,5,2,13]
max_match?(arr) #=> true
arr = [1,3,4,7,59]
max_match?(arr) #=> false
A few notes:
?
) or explanation (!
) mark at the end. Here a question mark seems appropriate.to_a
is not needed. Enumerable methods (e.g., any?
) can have Enumerators as receivers.n=arr.length
. for i in 1..arr.length
is enough, except...for ...
is rarely used. Rubyists tend to use each
instead, or one of the many methods from the Enumerable (mix-in) module (all of which invoke each
).return false
because Ruby returns the value of the last statement evaluated, which is false
if the method does not return true
earlier.Here's a more Ruby-like way to do that:
def max_match?(arr)
mx = arr.max
whats_left = arr - [mx]
(1..whats_left.size).any? {|n| whats_left.combination(n).any? {|c|
c.reduce(:+) == mx }}
end
arr = [1,4,7,3,5,2,13]
max_match?(arr) #=> true
arr = [1,3,4,7,59]
max_match?(arr) #=> false
If you wish this to return true
when arr
contains more than one value equal to mx
, insert the following after mx = arr.max
:
return true if arr.count(mx) > 1
Upvotes: 3