Ruby - print answer "if own answer (itself)" - ruby

Ruby question:
Can I shorten the following code:
total = Paper.where(available: true).count
puts total if total > 0
I imaged something like this, but I don't know if it's possible:
puts Paper.where(available: true).count if itself > 0
Is there a way to write this idea in one simple line?

if (total = Paper.where(available: true).count) > 0 then puts total end
Update: with an instance variable you can do
puts #total if (#total = Paper.where(available: true).count) > 0

What you have is perfect in every way. For fun, you could use Object#tap for a one-liner:
Paper.where(available: true).count.tap { |total| puts total if total > 0 }

The closest I can think of off the top of my head would be something like this:
total = Paper.where(available: true).count; puts total if total > 0
Its the exact same thing as your original except its separating the lines by a semi-colon instead of a new line. And its tends to be less readable, so I would generally avoid doing something like that.
As a side note, while I understand what you're trying to do, honestly, reducing your code from 2 lines to 1 is not a big deal. Frankly, its fine the way it is.

Related

ruby-progressbar expose count values

I want to access the count and total values from the ProgressBar instance. If they are exposed, I do not know how to get them. When I'm testing a loop, I may only want to iterate 10 times and break. It seems intuitive that either pb.increment would return the value, or that it would be an attr_reader value. Am I missing something?
require 'ruby-progressbar'
pb = ProgressBar.create(
title:'Items',
total:500,
remainder_mark:'.',
format:'%t |%B| %c of %C %p%%',
length:80
)
i = 0
500.times {|x|
pb.increment
break if (i+=1) > 100
}
pb.stop
As you can see, I have to create and maintain a separate counter. It just seems so intuitive to say "break if pb.increment > 10", or at least do "pb.increment; break if pb.count > 10".
Thanks, dvn
Update
You can access progress from the pb object, just as Anthony suggested:
break if pb.progress > 100
According to the docs, you can get all values as a hash with to_h and then use the 'progress' value:
break if pb.to_h['progress'] > 100

Optimizing Array Memory Usage

I currently have a very large array of permutations, which is currently using a significant amount of RAM. This is the current code I have which SHOULD:
Count all but the occurrences where more than one '1' exists or three '2's exist in a row.
arr = [*1..3].repeated_permutation(30).to_a;
count = 0
arr.each do |x|
if not x.join('').include? '222' and x.count(1) < 2
count += 1
end
end
print count
So basically this results in a 24,360 element array, each of which have 30 elements.
I've tried to run it through Terminal but it literally ate through 14GB of RAM, and didn't move for 15 minutes, so I'm not sure whether the process froze while attempting to access more RAM or if it was still computing.
My question being: is there a faster way of doing this?
Thanks!
I am not sure what problem you try to solve. If your code is just an example for a more complex problem and you really need to check programatically every single permumation, then you might want to experiment with lazy:
[*1..3].repeated_permutation(30).lazy.each do ||
# your condition
end
Or you might want to make the nested iteratior very explicit:
[1,2,3].each do |x1|
[1,2,3].each do |x2|
[1,2,3].each do |x3|
# ...
[1,2,3].each do |x30|
permutation = [x1,x2,x3, ... , x30]
# your condition
end
end
end
end
end
But it feels wrong to me to solve this kind of problem with Ruby enumerables at all. Let's have a look at your strings:
111111111111111111111111111111
111111111111111111111111111112
111111111111111111111111111113
111111111111111111111111111121
111111111111111111111111111122
111111111111111111111111111123
111111111111111111111111111131
...
333333333333333333333333333323
333333333333333333333333333331
333333333333333333333333333332
333333333333333333333333333333
I suggest to just use enumerative combinatorics. Just look at the patterns and analyse (or count) how often your condition can be true. For example there are 28 indexes in your string at which a 222 substring could be place, only 27 for the 2222 substring... If you place a substring how likely is it that there is no 1 in the other parts of the string?
I think your problem is a mathematics problem, not a programming problem.
NB This is an incomplete answer, but I think the idea might give a push to the proper solution.
I can think of a following approach: let’s represent each permutation as a value in ternary number base, padded by zeroes:
1 = 000..00001
2 = 000..00002
3 = 000..00010
4 = 000..00011
5 = 000..00012
...
Now consider we restated the original task, treating zeroes as ones, ones as twos and twos as threes. So far so good.
The whole list of permutations would be represented by:
(1..3**30-1).map { |e| x = e.to_s(3).rjust(30, '0') }
Now we are to apply your conditions:
def do_calc permutation_count
(1..3**permutation_count-1).inject do |memo, e|
x = e.to_s(3).rjust(permutation_count, '0')
!x.include?('111') && x.count('0') < 2 ? memo + 1 : memo
end
Unfortunately, even for permutation_count == 20 it takes more than 5 minutes to calculate, so probably some additional steps are required. I will be thinking of further optimization. Currently I hope this will give you a hint to find the good approach yourself.

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.

Declaring an integer Range with step != 1 in Ruby

UPDATE 2: For posterity, this is how I've settled on doing it (thanks to Jorg's input):
100.step(2, -2) do |x|
# my code
end
(Obviously there are plenty of ways to do this; but it sounds like this is the most "Ruby" way to do it; and that's exactly what I was after.)
UPDATE: OK, so what I was looking for was step:
(2..100).step(2) do |x|
# my code
end
But it turns out that I wasn't 100% forthcoming in my original question. I actually want to iterate over this range backwards. To my surprise, a negative step isn't legal.
(100..2).step(-2) do |x|
# ArgumentError: step can't be negative
end
So: how do I do this backwards?
I am completely new to Ruby, so be gentle.
Say I want to iterate over the range of even numbers from 2 to 100; how would I do that?
Obviously I could do:
(2..100).each do |x|
if x % 2 == 0
# my code
end
end
But, obviously (again), that would be pretty stupid.
I know I could do something like:
i = 2
while i <= 100
# my code
i += 2
end
I believe I could also write my own custom class that provides its own each method (?). I am almost sure that would be overkill, though.
I'm interested in two things:
Is it possible to do this with some variation of the standard Range syntax (i.e., (x..y).each)?
Either way, what would be the most idiomatic "Ruby way" of accomplishing this (using a Range or otherwise)? Like I said, I'm new to the language; so any guidance you can offer on how to do things in a more typical Ruby style would be much appreciated.
You can't declare a Range with a "step". Ranges don't have steps, they simply have a beginning and an end.
You can certainly iterate over a Range in steps, for example like this:
(2..100).step(2).reverse_each(&method(:p))
But if all you want is to iterate, then what do you need the Range for in the first place? Why not just iterate?
100.step(2, -2, &method(:p))
This has the added benefit that unlike reverse_each it does not need to generate an intermediate array.
This question answers yours: about ruby range?
(2..100).step(2) do |x|
# your code
end
I had similar issue here are the various ways I found to do the same SIMPLE thing I used step in the end because it allowed for NEGATIVE and FRACTIONAL increments and I had no conditions, other than the bounds to look for
case loop_type
when FOR
# doen't appear to have a negative or larger than 1 step size!
for kg in 50..120 do
kg_to_stones_lbs(kg)
end
when STEP
120.step(70,-0.5){ |kg|
kg_to_stones_lbs(kg)
}
when UPTO
50.upto(120) { |kg|
kg_to_stones_lbs(kg)
}
when DOWNTO
120.downto(50){ |kg|
kg_to_stones_lbs(kg)
}
when RANGE
(50..120).reverse_each{ |kg|
kg_to_stones_lbs(kg)
}
when WHILE
kg = 120
while kg >= 50
kg_to_stones_lbs(kg)
kg -= 0.5
end
end
O/P:
92.0kg - 14st 7lbs
91.5kg - 14st 6lbs
91.0kg - 14st 5lbs
90.5kg - 14st 4lbs
90.0kg - 14st 2lbs
89.5kg - 14st 1lbs
89.0kg - 14st 0lbs
88.5kg - 13st 13lbs
88.0kg - 13st 12lbs

how does Enumerable#cycle work? (ruby)

looper = (0..3).cycle
20.times { puts looper.next }
can I somehow find the next of 3? I mean if I can get .next of any particular element at any given time. Not just display loop that starts with the first element.
UPDATE
Of course I went though ruby doc before posting my question. But I did not find answer there ...
UPDATE2
input
looper = (0..max_cycle).cycle
max_cycle = variable that can be different every time the script runs
looper = variable that is always from interval (0..max_cycle) but the current value when the script starts could be any. It is based on Time.now.hour
output
I want to know .next value of looper at any time during the running time of the script
Your question is not very clear. Maybe you want something like this?
(current_value + 1) % (max_cycle + 1)
If, for example, max_cycle = 3 you will have the following output:
current_value returns
0 1
1 2
2 3
3 0
http://ruby-doc.org/core-1.9/classes/Enumerable.html#M003074

Resources