Reputation: 1271
I have a problem about the code
@nums = [3, 2, 4]
@target = 6
def two_sum(nums, target)
random1 = nums.sample
random2 = nums.sample
ary1 = [nums.index(random1), nums.index(random2)].sort
if random1 + random2 == target
return ary1
else
return 1
end
end
loop do
if two_sum(@nums, @target) != 1
print two_sum(@nums, @target)
break
end
puts 2
end
This code should return the indices of two elements in [3, 2, 4]
whose sum is 6
, i.e. either [1, 2]
or [0, 0]
. But occasionally 1
appears, although it shouldn't.
Why does it happen?
Upvotes: 1
Views: 115
Reputation: 114228
Your method's return value depends on a call to sample
, i.e. it returns a random – and therefore potentially different – element each time. The method name two_sum
however does not indicate its impure nature. If the method was called random_two_sum
, the bug would have been a lot more obvious:
if random_two_sum(@nums, @target) != 1
print random_two_sum(@nums, @target)
break
end
So unless you want that randomness, a better approach is to yield the values one after another using an Enumerator
:
def each_two_sum_index(nums, target)
return enum_for(__method__, nums, target) unless block_given?
nums.each_index.to_a.repeated_combination(2) do |i, j|
yield i, j if nums[i] + nums[j] == target
end
end
You can then invoke the method with a block instead of using an explicit loop
:
each_two_sum_index([3, 2, 4], 6) do |i, j|
p i: i, j: j
end
Output:
{:i=>0, :j=>0}
{:i=>1, :j=>2}
Upvotes: 1
Reputation: 66333
In this part of the code:
if two_sum(@nums, @target) != 1
print two_sum(@nums, @target)
you are making two separate calls to the two_sum
function, once in the if
and then a second time in the print
. So if the first result isn't equal to 1 you'll make a second call (which could return 1) and print the result from that second call.
Instead, you could capture the result of a single call to two_sum
and print that e.g.
loop do
result = two_sum(@nums, @target)
if result != 1
print result
...
or combining the assignment and comparison if you prefer:
if (result = two_sum(@nums, @target)) != 1
...
Upvotes: 4