Because Array
lets you put repeated elements of same value, I believe that the two lowest elements in [1, 2, 1]
are [1, 1]
, not [1, 2]
. This is the very same behavior one would face if sorting the array and getting the two first elements.
Also I believe that in [1]
there is a lowest and no 2nd lowest (also, the very same behavior if sorting and getting the first two).
With this in mind, I changed your code to obey these premises (and make it a bit more readable if I may say). Take a look.
def two_lowest arr
# if arr has no elements, there is no answer
# If arr has only one element, this is the lowest
if arr.size < 2 then
return arr.first, nil
end
lowest, second_lowest = nil, nil
arr.each do |n|
if lowest.nil? or n < lowest
# if we have no lowest or we found an element lower than current lowest,
# update our lowest and 2nd lowest
second_lowest = lowest
lowest = n
elsif second_lowest.nil? or n < second_lowest
# if we have no 2nd lowest or we found an element between lowest and 2nd
# lowest, update our 2nd lowest
second_lowest = n
end
end
return lowest, second_lowest
end
If you want to test it
tests = [
[],
[1],
[1, 1],
[1 ,2],
[1, 2, 1],
[1, 2, 3],
[1, 1, 2, 3],
[3, 2, 1, 1],
]
for test in tests
puts "In #{test}:"
puts "#{two_lowest test}"
puts
end
lowest, second_lowest = VERY_LARGE_NUMBER, VERY_LARGE_NUMBER
\$\endgroup\$Array#min
can return the two lowest values: [3,2,1].min(2) \$\endgroup\$