Ruby negated-if statements - ruby

I have a statement checking if a string contains another; if it doesn't, it runs some code. I don't think I'm doing it in a very optimised way. Here is a code snippet:
if blocks_in_progress.include? ('|' + blocks[i])
else
block = blocks[i]
break
end

Bit of a Ruby newbie here, but as far as I understand it, the following is the preferred way:
unless blocks_in_progress.include? ('|' + blocks[i])
block = blocks[i]
break
end
Source: https://github.com/bbatsov/ruby-style-guide (syntax section)

A one liner:
break block = blocks[i] unless blocks_in_progress.include? ('|' + blocks[i])

Related

What am I doing wrong with this simple If function in ruby

I have been trying to teach myself to code and have gravitated towards Ruby.
Upon working on if functions I have come across this problem where even if the user input is == to the answer variable it still comes back as false in the if function. It will not come back as true
I can get it to work if it is an Integer, but for some reason it always returns false when having a string. Tried to convert is as well but can not figure it out.
Thank you for any help.
puts("For each question select A, B, or C")
puts("What is the capital of Kentucky?")
puts()
puts("A. Louisville")
puts("B. Frankfort")
puts("C. Bardstown")
puts()
answer = String("B")
text = gets()
puts()
if text == answer
puts("correct")
else
puts("incorrect")
puts("The correct answer was " + answer + ".")
end
There is an additional method you can call when declaring the "text" variable that will solve this.
The method you used preserves a line break at the end when you press enter to submit an answer so it will never actually correspond to the answer. To remove the line break use the "chomp" method.
text = gets.chomp
Hope this helped. Good luck.

Ruby elegant alternative to ++ in nested loops?

Before anything, I have read all the answers of Why doesn't Ruby support i++ or i—? and understood why. Please note that this is not just another discussion topic about whether to have it or not.
What I'm really after is a more elegant solution for the situation that made me wonder and research about ++/-- in Ruby. I've looked up loops, each, each_with_index and things alike but I couldn't find a better solution for this specific situation.
Less talk, more code:
# Does the first request to Zendesk API, fetching *first page* of results
all_tickets = zd_client.tickets.incremental_export(1384974614)
# Initialises counter variable (please don't kill me for this, still learning! :D )
counter = 1
# Loops result pages
loop do
# Loops each ticket on the paged result
all_tickets.all do |ticket, page_number|
# For debug purposes only, I want to see an incremental by each ticket
p "#{counter} P#{page_number} #{ticket.id} - #{ticket.created_at} | #{ticket.subject}"
counter += 1
end
# Fetches next page, if any
all_tickets.next unless all_tickets.last_page?
# Breaks outer loop if last_page?
break if all_tickets.last_page?
end
For now, I need counter for debug purposes only - it's not a big deal at all - but my curiosity typed this question itself: is there a better (more beautiful, more elegant) solution for this? Having a whole line just for counter += 1 seems pretty dull. Just as an example, having "#{counter++}" when printing the string would be much simpler (for readability sake, at least).
I can't simply use .each's index because it's a nested loop, and it would reset at each page (outer loop).
Any thoughts?
BTW: This question has nothing to do with Zendesk API whatsoever. I've just used it to better illustrate my situation.
To me, counter += 1 is a fine way to express incrementing the counter.
You can start your counter at 0 and then get the effect you wanted by writing:
p "#{counter += 1} ..."
But I generally wouldn't recommend this because people do not expect side effects like changing a variable to happen inside string interpolation.
If you are looking for something more elegant, you should make an Enumerator that returns integers one at a time, each time you call next on the enumerator.
nums = Enumerator.new do |y|
c = 0
y << (c += 1) while true
end
nums.next # => 1
nums.next # => 2
nums.next # => 3
Instead of using Enumerator.new in the code above, you could just write:
nums = 1.upto(Float::INFINITY)
As mentioned by B Seven each_with_index will work, but you can keep the page_number, as long all_tickets is a container of tuples as it must be to be working right now.
all_tickets.each_with_index do |ticket, page_number, i|
#stuff
end
Where i is the index. If you have more than ticket and page_number inside each element of all_tickets you continue putting them, just remember that the index is the extra one and shall stay in the end.
Could be I oversimplified your example but you could calculate a counter from your inner and outer range like this.
all_tickets = *(1..10)
inner_limit = all_tickets.size
outer_limit = 5000
1.upto(outer_limit) do |outer_counter|
all_tickets.each_with_index do |ticket, inner_counter|
p [(outer_counter*inner_limit)+inner_counter, outer_counter, inner_counter, ticket]
end
# some conditional to break out, in your case the last_page? method
break if outer_counter > 3
end
all_tickets.each_with_index(1) do |ticket, i|
I'm not sure where page_number is coming from...
See Ruby Docs.

Employ early bail-out in MATLAB

There is a example for Employ early bail-out in this book (http://www.amazon.com/Accelerating-MATLAB-Performance-speed-programs/dp/1482211297) (#YairAltman). for speed improvement we can convert this code:
data = [];
newData = [];
outerIdx = 1;
while outerIdx <= 20
outerIdx = outerIdx + 1;
for innerIdx = -100 : 100
if innerIdx == 0
continue % skips to next innerIdx (=1)
elseif outerIdx > 15
break % skips to next outerIdx
else
data(end+1) = outerIdx/innerIdx;
newData(end+1) = process(data);
end
end % for innerIdx
end % while outerIdx
to this code:
function bailableProcessing()
for outerIdx = 1 : 5
middleIdx = 10
while middleIdx <= 20
middleIdx = middleIdx + 1;
for innerIdx = -100 : 100
data = outerIdx/innerIdx + middleIdx;
if data == SOME_VALUE
return
else
process(data);
end
end % for innerIdx
end % while middleIdx
end % for outerIdx
end % bailableProcessing()
How we did this conversion? Why we have different middleIdx range in new code? Where is checking for innerIdx and outerIdx in new code? what is this new data = outerIdx/innerIdx + middleIdx calculation?
we have only this information for second code :
We could place the code segment that should be bailed-out within a
dedicated function and return from the function when the bail-out
condition occurs.
I am sorry that I did not clarify within the text that the second code segment is not a direct replacement of the first. If you reread the early bail-out section (3.1.3) perhaps you can see that it has two main parts:
The first part of the section (which includes the top code segment) illustrates the basic mechanism of using break/continue in order to bail-out from a complex processing loop, in order to save processing time in computing values that are not needed.
In contrast, the second part of the section deals with cases when we wish to break out of an ancestor loop that is not the direct parent loop. I mention in the text that there are three alternatives that we can use in this case, and the second code segment that you mentioned is one of them (the other alternatives are to use dedicated flags with break/continue and to use try/catch blocks). The three code segments that I provided in this second part of the section should all be equivalent to each other, but they are NOT equivalent to the code-segment at the top of the section.
Perhaps I should have clarified this in the text, or maybe I should have used the same example throughout. I will think about this for the second edition of the book (if and when it ever appears).
I have used a variant of these code segments in other sections of the book to illustrate various other aspects of performance speedups (for example, 3.1.4 & 3.1.6) - in all these cases the code segments are NOT equivalent to each other. They are merely used to illustrate the corresponding text.
I hope you like my book in general and think that it is useful. I would be grateful if you would place a positive feedback about it on Amazon (direct link).
p.s. - #SamRoberts was correct to surmise that mention of my name would act as a "bat-signal", attracting my attention :-)
it's all far more simple than you think!
How we did this conversion?
Irrationally. Those two codes are completely different.
Why we have different middleIdx range in new code?
Randomness. The point of the author is something different.
Where is checking for innerIdx and outerIdx in new code?
dont need that, as it's not intended to be the same code.
what is this new data = outerIdx/innerIdx + middleIdx calculation?
a random calculation as well as data(end+1) = outerIdx/innerIdx; in the original code.
i suppose the author wants to illustrate something far more profoundly: that if you wrap your code that does (possibly many) loops (fors/whiles, doesnt matter) inside a function and you issue a return statement if you somehow detect that you're done, it will result in an effectively "bailable" computation, e.g. the method that does the work returns earlier than it would normally do. that is illustrated here by the condition that checks on data == SOME_VALUE; you can have your favourite bailout condition there instead :-)
moreover, the keywords [continue/break] inside the first example are meant to illustrate that you can [skip the rest of/leave] the inner-most loop from whereever you call them. in principal, you can implement a bailout using these by e.g.
bailing = false;
for outer = 1:1000
for inner = 1:1000
if <somebailingcondition>
bailing = true;
break;
else
<do stuff>
end
end
if bailing
break;
end
end
but that would be very clumsy as that "cascade" of breaks will need to be as long as you have nested loops and messes up the code.
i hope that could clarify your issues.

Ruby skips a section of script

Ruby noob here, and I am having an infuriating issue.
Something in my script is making Ruby skip a section of it.
#Main_block_begins_here
if __FILE__ == $0
#Open_the_file_with_values_and_weights
File.open(getFileName, 'r') do |f|
#Intial_data...
$totalNumber=f.gets.chomp!.to_i
$totalCapacity=f.gets.chomp!.to_i
$currentItemWeight=0
$currentItemValue=0
$spaceLeft=0
$spaceLeft=$totalCapacity
$takenWeight=0
$takenValue=0
#Make_a_heap_for_the_data
$prioQ = Heap.new do
#reads_values,_computes_them,_and_enqueues_them
until i==$totalNumber
total=0
value=f.gets.chomp!.to_i
weight=f.gets.chomp!.to_i
total=value/weight
puts "#{total}=t, #{value}=v, #{weight}=w. Correct?"
check=gets.chomp!
it=Obj.new(total, value, weight) do
prioQ.enqueue(it)
end
i+=1
end
end
#dequeueIt
puts "total weight taken was #{$takenWeight} and total value taken was #{$takenValue}."
end
end
The commented line #dequeueIt is a method earlier on that when I let run, it gives me an infinite loop with all values that were supposed to be read in from the text file as zeros.
The puts line and the check declaration line inside the until loop are for debugging purposes, and of course they never print out.
Commented out, when I run the program it just prints out the last line as if the until loop never ran. If more code for context is necessary, just let me know and I'll put it up.
My hair's starting to fall out over this one, so any help is appreciated!
EDIT:: Yes, it should have been i==$totalnumber. I fixed it in my code and it still doesn't execute the script inside that loop.
This is one oversight:
until i=$totalNumber
This assigns a number to i; it is always true. Try
until i==$totalNumber

Converting this into a Ruby one-liner

I'm currently trying to making my obfuscated, short mandelbrot set code into a one-liner, but I'm having a lot of trouble in doing so. \
It was originally written in Python, but due to Python's limitations, I could not compress the code to one line. So now I'm going to try Ruby. I'm familiar with the language, but I'm not very skilled in using blocks - which is where I am having the issue.
Anyway, the code I want to "convert" is
for q in range(801):
if q%40==0:print s;s=''
i,k=0,0
while(abs(k)<2*(i<15)):k,i=k**2+complex(q%40*.075-2,q/40*-.1+1),i+1
s+=h[i/3]
Which I've attempted to rewrite in Ruby...
h,s='.;*&8#',''
0.upto(800).each {|q|
if !q%40
s=''
p s
end
i,k=0,0
while(k.abs<2*(i<15))
k,i=k**2+Complex(q%40*0.075-2,q/40*-0.1+1),i+1
end
s+=h[i/3]
}
Which throws the error
Line 2:in `upto': no block given (LocalJumpError)
from t.rb:2
After sorting this out, I'd like to shorten it further to one line. Which I've started here...
h,s='.;*&8#','';0.upto(800).each {|q| if !q%40 then s='';p s end;i,k=0,0;while(k.abs<2*(i<15))do k,i=k**2+Complex(q%40*0.075-2,q/40*-0.1+1),i+1 end}
But anyway, I'm just doing this for fun, and hoping to learn a little more Ruby in the process. So if anyone can explain to me what is throw these errors, that would be great.
require 'complex'
h,s='.;*&8#',''
0.upto(800).each {|q|
if q%40 == 0
p s
s=''
end
i,k=0,0
while(k.abs<2 && (i<15))
k,i=k**2+Complex(q%40*0.075-2,q/40*-0.1+1),i+1
end
s+=h[i/3, 1]
}
Issues I dealt with:
Ruby conditionals return boolean values, not 1 or 0, and ! has a high priority
You were clobbering s before printing it
To work on 1.8.x and 1.9.x you need to index strings with [x, 1]
And here it is rearranged a little as a better starting point for a one-liner:
require 'complex'
h,s='.;*&8#',''
800.times { |q|
(p s; s='') if q%40 == 0
i,k=0,0
k,i=k**2+Complex(q%40*0.075-2,q/40*-0.1+1),i+1 while k.abs<2 && i<15
s+=h[i/3, 1]
}
Fist, get rid of the each, the block should go with upto. Once you did that, you'll get another error: undefined method '%' for false:FalseClass. This is because of !q%40, since precedence will first do the logical negation of q (anything but nil and false are true) and then try to evaluate false%40. Also you seem to assume that a zero would evaluate to false, which it doesn't. Then the next problem will be in the condition of your while loop, since k.abs<2 as well as i<15 evaluate to boolen values (`*': true can't be coerced into Fixnum). This should get you started...
Here's a multi-line version; feel free to put it all on one line:
h,s='.;*&8#','';
0.upto(800).each { |q|
(puts s;s='') if q%40==0;
i,k=0,0;
k,i=k**2+Complex(q%40*0.075-2,q/40*-0.1+1),i+1 while k.abs<2*(i<15?1:0);
s+=h[i/3]
}

Resources