I recently came up across a problem/solution that used Loop Do. I seldom have seen this so far in my learning Ruby Programming (I am a beginner with no CS experience).
# Write a function, `nearest_larger(arr, i)` which takes an array and an
# index. The function should return another index, `j`: this should
# satisfy:
#
# (a) `arr[i] < arr[j]`, AND
# (b) there is no `j2` closer to `i` than `j` where `arr[i] < arr[j]`.
#
# In case of ties (see example beow), choose the earliest (left-most)
# of the two indices. If no number in `arr` is largr than `arr[i]`,
# return `nil`.
#
# Difficulty: 2/5
describe "#nearest_larger" do
it "handles a simple case to the right" do
nearest_larger([2,3,4,8], 2).should == 3
end
it "handles a simple case to the left" do
nearest_larger([2,8,4,3], 2).should == 1
end
it "treats any two larger numbers like a tie" do
nearest_larger([2,6,4,8], 2).should == 1
end
it "should choose the left case in a tie" do
nearest_larger([2,6,4,6], 2).should == 1
end
it "handles a case with an answer > 1 distance to the left" do
nearest_larger([8,2,4,3], 2).should == 0
end
it "handles a case with an answer > 1 distance to the right" do
nearest_larger([2,4,3,8], 1).should == 3
end
it "should return nil if no larger number is found" do
nearest_larger( [2, 6, 4, 8], 3).should == nil
end
end
SOLUTION
def nearest_larger(arr, idx)
diff = 1
loop do
left = idx - diff
right = idx + diff
if (left >= 0) && (arr[left] > arr[idx])
return left
elsif (right < arr.length) && (arr[right] > arr[idx])
return right
elsif (left < 0) && (right >= arr.length)
return nil
end
diff += 1
end
end
nearest_larger([2,4,3,8], 1)
Can someone please explain to me when is the best time to use a "loop do" construct instead of the usual "while" or "unless" or "each" construct?
Looping in programming languages is a feature which clears the way for the execution of a set of instructions or functions repeatedly when some of the condition evaluates to true or false. Ruby provides the different types of loop to handle the condition based situation in the program to make the programmers task simpler. The loops in Ruby are :
With the help of doing keyword in Ruby while loop it will execute altealt once even the conditions get failed for the first time, which means even condition is false once the code block will execute on the starting of the execution. Below is the example are mentioned:
The main important facts of the ruby do-while loop are it will execute the loop at least once for the first time and then it will go for checking of the conditions. While Loops in ruby are based on the boolean value which means it works on the true and false value of the conditions.
It is also known as Entry Controlled Loop because the condition to be tested is present at the beginning of the loop body. for variable_name [, variable...] in expression [do] # code to be executed end for: A special Ruby keyword which indicates the beginning of the loop.
Adding up to the previous answers,
The "loop do" construct also offers a cleaner syntax when working with external iterators, e.g
No "loop do"
my_iterator = (1..9).each
begin
while(true)
puts my_iterator.next
end
rescue StopIteration => e
puts e
end
And now with "loop do" this would become
my_iterator = (1..9).each
loop do
puts my_iterator.next
end
And the exception is handled for you. It also allows you to loop through two collections at the same time and as soon as one of them runs out of elements the loop exits gracefully,
iterator = (1..9).each
iterator_two = (1..5).each
loop do
puts iterator.next
puts iterator_two.next
end
It will print: 1,1,2,2,3,3,4,4,5,5,6.
More info on it at: ruby-docs.org
In a language without loop
, you might use a while
construct like:
while( true ) {
# Do stuff until you detect it is done
if (done) break;
}
The point of it is that you start the loop without knowing how many of iterations to perform (or it is hard to calculate in advance), but it is easy to detect when the loop should end. In addition, for a particular case you might find the equivalent while (! done) { # do stuff }
syntax clumsy, because the done condition can happen halfway through the loop, or in multiple places.
Ruby's loop
is basically the same thing as the while( true )
- in fact you can use while( true )
almost interchangeably with it.
In the given example, there are following points of return within each iteration:
if (left >= 0) && (arr[left] > arr[idx])
return left # <-- HERE
elsif (right < arr.length) && (arr[right] > arr[idx])
return right # <-- HERE
elsif (left < 0) && (right >= arr.length)
return nil # <-- HERE
end
There is also an implied "else continue looping" here, if no end conditions are met.
These multiple possible exit points are presumably why the author chose the loop
construct, although there are many ways of solving this problem in practice with Ruby. The given solution code is not necessarily superior to all other possibilities.
Using the loop do
construct allows you to break on a conditional.
for instance:
i=0
loop do
i+=1
print "#{i} "
break if i==10
end
You would want to use this when you know the number of elements that will be processed, similar to that of the for each
loop
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With