Problem comprehending C-style ruby loops - ruby

I find the .each do hard to get to stick, so I was hoping for regular use of C for loop syntax which seems to not work, so I tried a while but still get errors.
I have tried this.
i = 0
while i < SampleCount
samples[i] = amplitude
amplitude *= -1
i++
end
I get complaints about the end statement here.

There are several problems with your code. Rather than just fixing the errors, I'd suggest it's better long-term for you to learn the Ruby way - it will save you time and energy later. In this case, it's
5.times do |i|
samples[i] = amplitude # assumes samples already exists and has 5 entries.
amplitude *= -1
end
If you insist on keeping a similar style, you can do this:
samples = []
i = 0
while i < sample_count
samples << amplitude # add new item to array.
amplitude *= -1
i += 1 # you can't use ++.
end
Note that SampleCount's initial capital letter, by Ruby convention, means a constant, which I'm guessing isn't what you really mean.

I agree with Peter that there are other (more idiomatic) ways to do this in Ruby, but just to be clear: the error message you saw misdirected you. There wasn't anything wrong with your while loop per se. The problem was i++ since there is no ++ operator in Ruby.
This would work just fine:
limit = 10
i = 0
while i < limit
puts i
i += 1
end
Again, I'm not recommending it, but if you're just learning the language, it may help to know where the problem really was.
Ruby has a lot of built-in ways to iterate other than for or while (which tend to be seen less often, as far as I can tell). A few other examples:
(1..10).each do |x| # 1..10 is a range which you can iterate over with each
puts x
end
1.upto(10) { |x| puts x } # Integers have upto and downto methods that can be useful

You originally mentioned trying to use a for loop. Notwithstanding the various other comments in the answers, here's the for loop approach:
for i in 0...5
samples[i] = amplitude
amplitude *= -1
end

Nobody here has actually offered an alternate solution that actually does what Fred originally intended - and that's iterate around the value of the constant SampleCount. So could you do:
SampleCount.times do |i|
Or:
limit = SampleCount
limit.times do |i|
Or:
for i in 0..SampleCount
Would any of those be Ruby-esque enough?

The problem with the end statement is related to i++. Ruby wants to add something. There is no increment operator in Ruby. You need to use i += 1. With that change you can use your C style loop as is.

Related

program using while with array values

I am trying to write a small program that goes through an array's values outputting each individual value. When it reaches 15 it stops and outputs "too big".
Why is my logic below wrong, it makes sense to me..
x = [10,11,12,13,14,15,16,17,18]
def counting
for x[y]
while y < 15
puts y
else
puts "too big"
end
puts counting
I'm just learning sorry if this is a really simple solution.
That's nothing at all like Ruby syntax. You want a .each and a simple if statement:
x.each do |y|
if y < 15
puts y
else
puts "too big"
break
end
end
It appears though you are trying to use Ruby like you would a c-style programming language. It's possible and viable, albeit not recommended.
Code Blocks
Ruby has structure known as code blocks. Code blocks are sort of like anonymous functions.
You can read more about code blocks here.
x = [10,11,12,13,14,15,16,17,18]
# This is a code block.
x.each do |y| # The y between the '|'s is the parameter caught by the code block
if y < 15
puts y
else
puts "Too big."
break # Break out of the loop
end
end
If you want a one liner:
x.each {|y| y < 15 ? puts(y) : puts("too big") || break }
If you insist using while, it can be done as following:
i = 0
while i do
x[i] < 15 ? puts(x[i]) : puts("too big") || break
i+=1
end
I think the cleanest way to do this using while would be:
def counting(x)
i = 0
while x[i] < 15
puts x[i]
i += 1
end
puts 'too big'
end
counting([10,11,12,13,14,15,16,17,18])
Why is my logic below wrong, it makes sense to me..
Given that you program isn't even syntactically legal, it's impossible to tell what its semantics would be if it were syntactically legal, let alone why those semantics were wrong. However, here's an idiomatic Ruby solution (you will almost never use nor see while in any Ruby code, and you will certainly never see for):
puts x.take_while {|n| n < 15 }
puts 'too big'
I prefer writing in point-free style, however in this case the only way to do that is to make use of the symmetry of the condition and invert the order of operands, which will lead to awkward logic:
x.take_while(&15.method(:>))
Ao, in this case I would rather avoid point-free style, because it no longer matches the original specification literally. Instead of "take all numbers less than 15", we now have "take all numbers such that 15 is greater than those numbers", which reads awkward.

Do something infinitely many times with an index

In more ruby way of doing project euler #2 , part of the code is
while((v = fib(i)) < 4_000_000)
s+=v if v%2==0
i+=1
end
Is there a way to change i += 1 into a more functional programming style construct?
The best I can think of is
Float::MAX.to_i.times do |i|
v = fib(i)
break unless v < 4_000_000
s += v if v%2==0
end
because you can't call .times on a floating point number.
Numeric.step has default parameters of infinity (the limit) and 1 (the step size).
1.step do |i|
#...
end
For fun, you might even want to try
1.step.size
There’s a predefined (in 1.9.2) constant Float::INFINITY, so you could write
1.upto(Float::INFINITY) do |i|
...
end
(You could also use Enumerator and take_while, turning the problem inside out to make it look more like Haskell or Python, but take_while is greedy and builds an array.)
Ruby 2.5 introduced the open-ended Range:
(1..).each do |i|
#...
end

Ruby .times .upto .downto, etc. Offsetting the printed value

Is there a way to offset the value that has been passed in the code block.
For example
C# - This will always print 5
for (int i = 0; i < 10; i++)
{
i=5
Console.WriteLine(i);
}
Ruby - This will print 5 for only 10 times.
10.times do |i|
i = 5
puts i
end
Is there a way to get |i| to get back to 5?
and another question. How can you make .times block skip(not increasing by 1 all the time)
No, you can't reset the counter of times, upto etc. from within the block.
You can use redo to restart the current iteration of the loop, which in this case will have a similar effect:
10.times do |i|
i = 5
puts i
redo
end
This will print 5 forever (though take note, that the initial value of i will still be 0 at each iteration).
If you need more control than this, you need to use a while loop. Though I'd advice that in most cases where you think you need this, you actually don't and you're just approaching your problem from the wrong angle.
You can use the 'next' keyword to skip iterations based on certain criteria if need be.
10.times do |i|
next if i < 5
puts i
end
Also you may use the keyword 'redo' as described by sepp2k.
This will print the value 5 ten times.
i=5
10.times{puts i}

Ruby shortest way to write rnd hex

What I have is a method used to generate random hex values. E.g 666 or FF7
However, I don't think it looks simple/elegant at all.. What I want is to make it more simple which perhaps will make my code shorter as well, but I don't know how. That is why I need tips or hints
Here is my code so far:
def random_values
random_values = Array.new
letters = ['A','B','C','D','E','F']
for i in 1..15
if i <= 9
random_values << i
else
random_values << letters[i-10]
end
end
return random_values.shuffle[0].to_s + random_values.shuffle[0].to_s + random_values.shuffle[0].to_s
end
As you probably see, I do not generate random numbers. I just shuffle the array containing the values I want, meaning all the numbers in the array are unique, which is not needed, but was the easiest solution for me when I wrote the code.
I am most concerned about the return line.. If only it was possible to write like:
return 3.times { random_values.shuffle[0] }
or
return random_values.shuffle[0].to_s *3
Thanks in advance!
def random_value
r = Random.new
((r.rand * 16)).to_i.to_s(16)
end
puts random_value + random_value + random_value
Or, after some quick research:
"%06x" % (rand * 0xffffff)
From Ruby, Generate a random hex color
Also, you shouldn't be looking for a more efficient solution per se. You seem to be looking for something more elegant, simple, and intuitive. (My solution is none of these, by the way. The searched one is.)
# For Ruby 1.9
require 'securerandom'
SecureRandom.hex(16)
# For Ruby 1.8 and above
require 'active_support/secure_random'
ActiveSupport::SecureRandom.hex(16)
Something like this?
(rand * MAX_VALUE).to_i.to_s(16)
Where MAX_VALUE is the upper bound for the numbers. You can also add some lower bound:
(MIN_VALUE + rand * (MAX_VALUE - MIN_VALUE)).to_i.to_s(16)
This will give you numbers in the range [MIN_VALUE,MAX_VALUE)

Idiomatic ruby for temporary variables within a method

Within a method, I am using i and j as temporary variables while calculating other variables. What is an idiomatic way of getting rid of i and j once they are no longer needed? Should I use blocks for this purpose?
i = positions.first
while nucleotide_at_position(i-1) == nucleotide_at_position(i)
raise "Assumption violated" if i == 1
i -= 1
end
first_nucleotide_position = i
j = positions.last
while nucleotide_at_position(j+1) == nucleotide_at_position(j)
raise "Assumption violated" if j == sequence.length
j += 1
end
last_nucleotide_position = j
Background: I'd like to get rid of i and j once they are no longer needed so that they aren't used by any other code in the method. Gives my code less opportunity to be wrong. I don't know the name of the concept - is it "encapsulation"? The closest concepts I can think of are (warning: links to TV Tropes - do not visit while working) Chekhov'sGun or YouHaveOutlivedYourUsefulness.
Another alternative would be to put the code into their own methods, but that may detract from readability.
What makes you think splitting the code up into multiple methods will hurt the readability? In my experience, splitting even small or medium sized pieces of code into multiple methods can greatly improve readability.
Ruby (like JS) doesn't create a new scope for each block by default (as C++, etc. do). However, in Ruby 1.9, you can try:
last_nucleotide_position = nil
proc { |;i, j|
i = positions.first
while nucleotide_at_position(i-1) == nucleotide_at_position(i)
raise "Assumption violated" if i == 1
i -= 1
end
first_nucleotide_position = i
j = positions.last
while nucleotide_at_position(j+1) == nucleotide_at_position(j)
raise "Assumption violated" if j == sequence.length
j += 1
end
last_nucleotide_position = j
}.call()
See How to make block local variables the default in ruby 1.9?. Any variables that you want to be used outside the block should be defined before-hand (like last_nucleotide_position).
FM is right that a separate method may be more readable.
I think the term you are looking for is variable scope -- in other words, you are looking for ways to confine the scope of i and j. But you don't need to worry about that. The problem at hand calls for creating separate methods -- regardless of scope considerations.
This will improve readability, because it will allow the reader to grok the code starting at the high level and then boring in deeper only as needed. It will also improve testability because your small methods will do exactly one thing.
def calc_first_nucleotide_position(po)
i = po.first
while nucleotide_at_position(i-1) == nucleotide_at_position(i)
raise "Assumption violated" if i == 1
i -= 1
end
i
end
# etc...
first_nucleotide_position = calc_first_nucleotide_position(positions)
last_nucleotide_position = calc_last_nucleotide_position(positions)
# etc...
You are looking for the Ruby equivalent of Lisp's let special operator. Ruby does not support it out of the box but you can hack it in very easily, and the resulting syntax is like this:
x = 10
scope { |x|
x = 30
}
puts x #=> 10
see: http://banisterfiend.wordpress.com/2010/01/07/controlling-object-scope-in-ruby-1-9/
If all you want is to keep new variables from spilling out into the rest of your program, you can wrap your code in a block using 1.times. Any new variables you create inside the block will be destroyed when you close the block. Just keep in mind that any changes you make to pre-existing variables will remain once the block closes.
y = 20
1.times do
# put your code in here
i = 1
puts x = y # => 20, because y is available from outside the block
y = 'new value' # We can change the value of y but our changes will
# propagate to outside the block since y was defined before we opened
# the block.
end
defined? i # => nil, i is lost when you close the block
defined? x # => nil, x is also local to the block
puts y # => 'new value'

Resources