How to execute multiple succeeding functions in 1 line in Ruby? - ruby

I have two succeeding function with the same condition and I wonder what is the best way to write this? I know the one way to do this is using if (condition) ... end, but I'm wondering if I can do it in one-line similar to bash, '[$n == $value] echo "$n" && break'.
n = 0
loop do
puts n if n == value # puts and break is having the same condition, but
break if n == value # can we do it in one line?
n += 1
end

Because n is truthy, you can use the 'and' joiner. It reads really nicely:
n = 0
loop do
puts n and break if n == value
n += 1
end
--edit--
As pointed out in comments, that won't actually work because puts returns nil, which isn't truthy. My bad. You can use 'or' instead, but that doesn't read nicely. So I'd say just group the statements with parenthesis.
n = 0
loop do
(puts n; break) if n == value
n += 1
end
You could also change the puts method to return the value it prints, and that would work with 'and', but that's probably not the smartest idea :)
I'm guessing your actual code is different to what you've pasted, so if the first method in your chain returns something, you can use 'and'.

One easy way is to just parenthesize the statements:
ruby-1.9.1-p378 > 0.upto(5) do |n|
ruby-1.9.1-p378 > (puts n; break;) if n == 3
ruby-1.9.1-p378 ?> puts ">>#{n}<<"
ruby-1.9.1-p378 ?> end
>>0<<
>>1<<
>>2<<
3
If it's a bit much to put in parentheses, a begin-end will do the trick:
0.upto(5) do |n|
begin
puts "I found a matching n!"
puts n
puts "And if you multiply it by 10, it is #{10*n}"
break;
end if n == 3
puts "((#{n}))"
end
Output:
((0))
((1))
((2))
I found a matching n!
3
And if you multiply it by 10, it is 30

proc { puts n; break; }.() if n == 3

One of the golden rules of Ruby is that if you are writing a loop, you are probably doing it wrong. In this particular case, all that your loop is doing is to find an element in a collection. In Ruby, there already is a method for finding an element in a collection: Enumerable#find. There is no need to write your own.
So, the code gets simplified to:
puts (0...1.0/0).find {|n| n == value }
Now that we have a nice declarative formulation of the problem, it is easy to see that (assuming sane equality semantics and sane semantics of value.to_s), this is exactly the same as:
puts value
So, the whole loop was completely unnecessary to begin with.

Related

Understanding this Ruby program concerned with prime numbers

This is a program that came from a textbook:
# Initialize our counter
i = 1
# i: [0, 100]
while (i <= 100)
# Initialize prime flag
prime_flag = true
j = 2
# Test divisibility of i from [0, i/2]
while (j <= i / 2)
# puts " i ==> " to i.to_s + " j ==> " + j.to_s
if (i % j == 0)
prime_flag = false
# break
end
j = j + 1
end
# We found a prime!
if prime_flag
puts "Prime ==> " + i.to_s
end
# Increment the counter
i += 1
end
The while (j <= i / 2) introduces a new loop. What if we are trying to find prime numbers. Why is this written? Prime numbers don't have square roots. What is the purpose of j being <= i / 2? I do not understand why j is introduced.
You are correct that you should be only checking numbers <= floor(sqrt(i)). The above code is unnecessarily checking numbers from ceil(sqrt(i)) through i/2. It would give the correct answer, however.
In addition, this is not very Ruby-like code. It's terrible and the author should feel terrible (unless they intended to show you something bad in order for you to be amazed when you see how you can write it better!).
Here's the same code done in a more Ruby-like manner. Note that prime? can definitely be a one-liner, but I split things on to more lines readability in the context of the question:
def prime?(i) # Define a function that takes 1 parameter `i`
MAX_NUM_TO_CHECK = Math.sqrt(i) # No need to check numbers greater than sqrt(i)
(2..MAX_NUM_TO_CHECK).all? do |j| # Return `true` if the following line is true for
# all numbers [2,MAX_NUM_TO_CHECK]
i % j != 0 # true if `i` is evenly not divisible by `j`. Any
# input that evaluates to false here is not prime.
end
end
# Test primality of numbers [1,100]
(1..100).each {|n| puts "Prime ==> #{n}" if prime? n}
I think the biggest differences between your book and this code are:
The algorithm is different in that we do not check all values, but rather limit the checks to <= sqrt(i). We also stop checking once we know a number is not prime.
We iterate over Ranges rather than keeping counters. This is slightly higher level and easier to read once you get the syntax.
I split the code into two parts, a function that calculates whether a parameter is prime or not, and then we iterate over a Range of inputs (1..100). This seems like a good division of functionality to me, helping readability.
Some language features used here not in your example:
If statements can go after expressions, and the expression is only evaluated if the predicate (the thing after the if) evaluates to true. This can make some statements more readable.
A range is written (x..y) and allows you to quickly describe a series of values that you can iterate over without keeping counters.
Code inside
do |param1, ..., paramN| <CODE>; end
or
{|param1, ..., paramN| <CODE>}
is called a block. It's an anonymous function (a function passed in as a parameter to another function/method). We use this with all? and each here.
each is used to run a block of code on each element of a collection, ignoring the return value
all? can be used to determine whether a block returns true for every item in a collection.
If you're not familiar with passing code into functions, this is probably a little confusing. It allows you to execute different code based on your needs. For example, each runs the yielded block for every item in the collection.You could do anything in that block without changing the definition of each... you just yield it a block and it runs that block with the proper parameters. Here is a good blog post to get you started on how this works and what else you can use it for.

How do I make each array element to be a divisor of a particular value in Ruby?

I am writing this program to find prime numbers between 1 and 100 without using req prime.
Program to find prime numbers between 1 and 100
divisors = [2,3,5,7,9,11,13,15]
arr = divisors.to_a
(1..100).each do |value|
if ((value % (arr.each do |n|) != 0))
puts "#{value}"
end
end
What could make each element in array to divide the value as a divisor? What am I missing here?
You have many glitches in your code, and the main is: it has an incorrect syntax and won’t be accepted by ruby parser.
The code below will work, but you should consider reading kinda tutorial on ruby syntax.
divisors = [2,3,5,7,9,11,13]
(1..100).each do |value|
unless divisors.any? { |d| value % d == 0 }
puts "#{value}"
end
end
The number is prime if and only it has no dividers. Using unless in conjunction with Enumerable#any? we check for the negation of exactly opposite: whether there are no such d in dividers, so that value % d is zero, we are done.

When and Why use Loop Do Construct in Ruby

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?
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
loop with 'loop' construct will execute the given block endlessly
until the code inside the block breaks on certain condition.
it can be used when you don't have a collection to loop over, the
places where 'each' and 'for' cannot work.
the different between 'loop' and while/until is that while/until will
execute the given block when certain condition is meet, where as in
case of loop there is no condition to start, condition lies inside the
loop's block.
for better understanding read doc.
http://www.ruby-doc.org/core-1.9.2/Kernel.html#method-i-loop
Suppose You wanted to put a number of conditions, it might be neater to put them together. Instead of this, for example:
x = 0
while x <= 10
num = gets.to_f
break if num < 1
break if /\D/.match? num.to_s
puts num ** 2
end
Grouping the breaks together makes it more readable
x = 0
loop do
num = gets.to_f
break if num < 1
break if x <= 10
break if /\D/.match? num.to_s
puts num ** 2
end

Confusion with the order of execution when `next` with `unless` in ruby

The next statement is used to skip a part of the loop and continue with the next iteration of the loop. It can be used in combination with for and while statements.
I have seen people using next if there is complicated piece of code after some condition is being evaluated i.e
next if #state!=:some_state
# some long complicated code
Now here I have played with the next in my IRB as below :
n = 1
loop do
n = n + 1
next unless n == 10
print "Good"
break
end
# Good=> nil
The above one understood. Nicely clear.
n = 1
#=> 1
loop do
print "#{n}"
n = n + 1
next puts "hi" unless n == 5
p "good"
break
end
#1hi
#2hi
#3hi
#4"good"
#=> nil
In the above code, couldn't understand about which order the lines puts "hi" and unless n == 5 executed. Which executed first?
The below one leads to the infinite Loop.
n = 1
#=> 1
loop do
print "#{n}"
n = n + 1
next puts "hi"; 2 + 3 unless n == 5
p "good"
break
end
whereas this one is good:
n = 1
#=> 1
loop do
print "#{n}"
n = n + 1
next puts "hi", 2 + 3 unless n == 5
p "good"
break
end
#1hi
#5
#2hi
#5
#3hi
#5
#4"good"
#=> nil
Please help me here to understand - how does this one resolve that forever loop ?
A semicolon is evaled as a line break so:
next puts "hi"; 2 + 3 unless n == 5
would be equivalent to:
next puts "hi"
2 + 3 unless n == 5
Therefore, next will always be called and you'll have an infinite loop.
The comma is evaled as passing a set of arguments (which is interpreted as an array by puts method signature), so:
next puts "hi", 2 + 3 unless n == 5
is equivalent to:
next puts("hi", 2 + 3) unless n == 5
Regarding the execution order of puts and unless - consider the following:
unless n == 5
next puts "hi"
end
In this example, it is obvious that unless is evaluated first, then if the condition passed is evaluated to false the next puts "hi" statement is executed. Well:
next puts "hi" unless n == 5
is shorthand for exactly the same thing. So the unless modifier will always be evaluated first. Naturally, if you insert a semicolon in the middle, it would cause this to be evaluated differently, since the semicolon is evaluated as a line break.
The conditional has to execute first, otherwise, how would it even know whether to evaluate any expressions involving the statement?
As to your second question, the value of the next expression is ignored for loops, the value in the expression is only useful to return a value from a block. So, the only thing that makes your loop end is the break.

"Or" in If Blocks in Ruby

So I am writing a Ruby program for school that changes the value of a boolean to true if a certain value is either 1 or 3, and to false if it is 0 or 2. Since I come from a Java background, I thought that this code should work: if n == 1 || n == 3
But it does not. So my question here is is it possible to use an "Or" expression thingy in If blocks in Ruby? I know that my current situation could be solved easily by just something like the following:
if n == 0
t_o_f = false
elsif n == 1
t_o_f = true
Et Cetera. But I want to know if I can use an Or in If blocks for the future.
Yes, any expression can be used in an if condition, including those using the || (logical or) operator.
As with Java, Ruby's || operator short-circuits. That is, if the left side is true, the right side is not evaluated.
Idiomatic ruby uses postfix if for one-liners:
puts "Yes" if n == 4 || n == 5
Avoid postfix if the line is long, however, and break it into multiple lines:
if n == 4 || n == 5
puts "This is a big long string to be output....................."
end
That's because postfix if can get visually lost at the end of a long line.
You can have a one-liner with prefix if, but it's not commonly seen:
if n == 4 || n == 5 then puts "foo" end
or, perhaps:
if n == 4 || n == 5 ; puts "foo" ; end
This is really a multi-line if condensed into one line; the semicolons act as line breaks.
When testing for multiple conditions, it can sometimes be valuable to use Array#include?:
puts "foo" if [4, 5].include?(n)
The value of this for only two conditions is not that great. For three or more, it reads well.
The or operator works, and you can write the keyword too:
if n==1 or n==2
end
http://www.tutorialspoint.com/ruby/ruby_operators.htm
And you could also write what you want this way:
x = (n%2) ? true : false
In addition to #Wayne Conrad: if there is little or no 'logic' deciding if n is true or false, then this is also a good option:
result = case n
when 1, 3 then true
when 0, 2 then false
end

Resources