C(++) For Loop Equivalents

What is the most efficient way in Ruby to create a conditional loop in
Ruby that looks like this in C(++):

for(int i=0; i*j/2<maxNum; i++)
{
  //cool method stuff
}

I was looking at the .upto() method but it doesn't like the comparison
operator :-/

Thanks!

What is the most efficient way in Ruby to create a conditional loop in
Ruby that looks like this in C(++):

for(int i=0; i*j/2<maxNum; i++)
{
  //cool method stuff
}

I was looking at the .upto() method but it doesn't like the comparison
operator :-/

Wouldn't it be better to figure out what you're trying to do than look
for a general construct?

  >> max = 200
  => 200
  >> j = 35
  => 35
  >> i = 0
  => 0
  >> 0.upto(max) { |i| break if (i * j / 2) >= max }
  => nil
  >> i
  => 12

That will do the job.

-austin

···

On 3/19/07, studlee2 <studlee2@gmail.com> wrote:
--
Austin Ziegler * halostatue@gmail.com * http://www.halostatue.ca/
               * austin@halostatue.ca * You are in a maze of twisty little passages, all alike. // halo • statue
               * austin@zieglers.ca

What is the most efficient way in Ruby to create a conditional loop in
Ruby that looks like this in C(++):

for(int i=0; i*j/2<maxNum; i++)
{
  //cool method stuff
}

In the general case, you can 'while' anywhere where you'd normally 'for'

i=0
while i*j/2<maxNum
  //cool method stuff
  i++
end

But 'most efficient way' to do a conditional loop depends on your
context (and also what you're trying to make efficient - runtime?
writetime? readtime?).

Dan.

studlee2 wrote:

What is the most efficient way in Ruby to create a conditional loop in
Ruby that looks like this in C(++):

for(int i=0; i*j/2<maxNum; i++)
{
  //cool method stuff
}

I was looking at the .upto() method but it doesn't like the comparison
operator :-/

Thanks

Why not just do:
((maxNum*2)/(i*j)).times do |n|
    #cool method stuff
end

Use the step method:

----------------------------------------------------------- Numeric#step
      num.step(limit, step ) {|i| block } => num

···

------------------------------------------------------------------------
      Invokes _block_ with the sequence of numbers starting at _num_,
      incremented by _step_ on each call. The loop finishes when the
      value to be passed to the block is greater than _limit_ (if _step_
      is positive) or less than _limit_ (if _step_ is negative). If all
      the arguments are integers, the loop operates using an integer
      counter. If any of the arguments are floating point numbers, all
      are converted to floats, and the loop is executed _floor(n +
      n*epsilon)+ 1_ times, where _n = (limit - num)/step_. Otherwise,
      the loop starts at _num_, uses either the +<+ or +>+ operator to
      compare the counter against _limit_, and increments itself using
      the +++ operator.

         1.step(10, 2) { |i| print i, " " }
         Math::E.step(Math::PI, 0.2) { |f| print f, " " }

      _produces:_

         1 3 5 7 9
         2.71828182845905 2.91828182845905 3.11828182845905

So your example would become:
0.step(i*j/2, 1) # (I'm not too sure about the details of C++ and if defining i in the beginning would make i*j/2 be 0 no matter what)
Or, you could do
0.upto(i*j/2) # assumes step is one.

Finally, you could do
for i in 0..(i*j/2) do |i|
  # blah...
end

Daniel Sheppard wrote:

What is the most efficient way in Ruby to create a conditional loop in
Ruby that looks like this in C(++):

for(int i=0; i*j/2<maxNum; i++)
{
  //cool method stuff
}

In the general case, you can 'while' anywhere where you'd normally 'for'

i=0
while i*j/2<maxNum //cool method stuff
  i++
end

But 'most efficient way' to do a conditional loop depends on your
context (and also what you're trying to make efficient - runtime?
writetime? readtime?).

Dan.

Raj Sahae wrote:

studlee2 wrote:

What is the most efficient way in Ruby to create a conditional loop in
Ruby that looks like this in C(++):

for(int i=0; i*j/2<maxNum; i++)
{
  //cool method stuff
}

I was looking at the .upto() method but it doesn't like the comparison
operator :-/

Thanks

Why not just do:
((maxNum*2)/(i*j)).times do |n|
   #cool method stuff
end

He would need to initialize i before your code as it could be any value, not just 0. By the same token the increment could be any number, not just 1.
A further problem with your method is that the loop is executed until i*j/2 is greater than maxNum. As you don't know if the loop somehow modifies the value of j you can not optimize it out. A simple example would be where the program reads some numbers from a file and adds them to j. i is incremented by one each time a number is read. You want the program to exit when i*j/2 is larger than maxNum.

# He would need to initialize i before your code as it could be
# any value,
# not just 0. By the same token the increment could be any number, not
# just 1.

fwiw, this is a simple example (intended for nubies only).

C:\family\ruby>cat -n test.rb
     1 #---------------------------
     2 #emulate c++ for (the better)
     3 #for(int i=0; i*j/2<maxNum; i++)
     4 # {
     5 # //cool method stuff
     6 # }
     7 #---------------------------
     8
     9 # using normal while loop
    10 puts "using while..."
    11 j=20
    12 i=0
    13 maxnum=100
    14 while i*j/2 < maxnum do
    15 puts i
    16 i+=1
    17 end
    18
    19 # let's make our own for() and call it for_simple :slight_smile:
    20 # note, there's no condition here
    21 # we're leaving it up to yield/blocks since that
    22 # is the ideal way, imho
    23 def for_simple (init=0,incr=1)
    24 i = init
    25 loop do
    26 yield i
    27 i += incr
    28 end
    29 end
    30
    31 # now let's test it
    32 puts <<TEXT
    33 Test I.
    34 using our own simple for()... note advantage,
    35 we don't need to track the counter...
    36 TEXT
    37
    38 for_simple do |i|
    39 break unless i*j/2 < maxnum
    40 puts i
    41 end
    42
    43 puts <<TEXT
    44 Test II.
    45 here we initialize to 2 and increment by 2
    46 again, we don't need to track the counter...
    47 TEXT
    48
    49 for_simple(2,2) do |i|
    50 break unless i*j/2 < maxnum
    51 puts i
    52 end
    53
    54 puts <<TEXT
    55 Test III.
    56 again, here we initialize to 200 and decrement by 20
    57 again, we don't need to track the counter...
    58 and note, we change keyword unless to if
    59 ruby just simply rocks..
    60 TEXT
    61
    62 for_simple(200,-20) do |i|
    63 break if i*j/2 < maxnum
    64 puts i
    65 end

C:\family\ruby>ruby test.rb
using while...
0
1
2
3
4
5
6
7
8
9
Test I.
using our own simple for()... note advantage,
we don't need to track the counter...
0
1
2
3
4
5
6
7
8
9
Test II.
here we initialize to 2 and increment by 2
again, we don't need to track the counter...
2
4
6
8
Test III.
again, here we initialize to 200 and decrement by 20
again, we don't need to track the counter...
and note, we change keyword unless to if
ruby just simply rocks..
200
180
160
140
120
100
80
60
40
20

C:\family\ruby>

Hth.
kind regards -botp

···

From: Michael W. Ryder [mailto:_mwryder@worldnet.att.net] :

Peña wrote:

From: Michael W. Ryder [mailto:_mwryder@worldnet.att.net] :

# He would need to initialize i before your code as it could be # any value, # not just 0. By the same token the increment could be any number, not # just 1.

fwiw, this is a simple example (intended for nubies only).

C:\family\ruby>cat -n test.rb
     1 #---------------------------
     2 #emulate c++ for (the better)
     3 #for(int i=0; i*j/2<maxNum; i++)
     4 # {
     5 # //cool method stuff
     6 # }
     7 #---------------------------
     8
     9 # using normal while loop
    10 puts "using while..."
    11 j=20
    12 i=0
    13 maxnum=100
    14 while i*j/2 < maxnum do
    15 puts i
    16 i+=1
    17 end
    18
    19 # let's make our own for() and call it for_simple :slight_smile:
    20 # note, there's no condition here
    21 # we're leaving it up to yield/blocks since that
    22 # is the ideal way, imho
    23 def for_simple (init=0,incr=1)
    24 i = init
    25 loop do
    26 yield i
    27 i += incr
    28 end
    29 end
    30
    31 # now let's test it
    32 puts <<TEXT
    33 Test I.
    34 using our own simple for()... note advantage,
    35 we don't need to track the counter...
    36 TEXT
    37
    38 for_simple do |i|
    39 break unless i*j/2 < maxnum
    40 puts i
    41 end
    42
    43 puts <<TEXT
    44 Test II.
    45 here we initialize to 2 and increment by 2
    46 again, we don't need to track the counter...
    47 TEXT
    48
    49 for_simple(2,2) do |i|
    50 break unless i*j/2 < maxnum
    51 puts i
    52 end
    53
    54 puts <<TEXT
    55 Test III.
    56 again, here we initialize to 200 and decrement by 20
    57 again, we don't need to track the counter...
    58 and note, we change keyword unless to if
    59 ruby just simply rocks..
    60 TEXT
    61
    62 for_simple(200,-20) do |i|
    63 break if i*j/2 < maxnum
    64 puts i
    65 end

C:\family\ruby>ruby test.rb
using while...
0
1
2
3
4
5
6
7
8
9
Test I.
using our own simple for()... note advantage,
we don't need to track the counter...
0
1
2
3
4
5
6
7
8
9
Test II.
here we initialize to 2 and increment by 2
again, we don't need to track the counter...
2
4
6
8
Test III.
again, here we initialize to 200 and decrement by 20
again, we don't need to track the counter...
and note, we change keyword unless to if
ruby just simply rocks..
200
180
160
140
120
100
80
60
40
20

C:\family\ruby>

Hth.
kind regards -botp

Now is it possible, like in Scheme, to assign a variable to a string and have Ruby evaluate the string? For example, f = "i*j/2". This would allow one to make a more generic version of your methods. Ideally you would have for_opt (i=0, f, inc=1) and have the method evaluate each of the variables if necessary. This would allow one to copy working C code without having to remember to do a lot of extraneous coding.

Is there any reason you can't use the syntactical sugar "for"? Or maybe
construct a range:

(i...((maxNum*2)/j) ).each_with_index do |stuff| end

···

On 3/20/07, Michael W. Ryder <_mwryder@worldnet.att.net> wrote:

Peña wrote:
> From: Michael W. Ryder [mailto:_mwryder@worldnet.att.net] :
>
> # He would need to initialize i before your code as it could be
> # any value,
> # not just 0. By the same token the increment could be any number, not
> # just 1.
>
> fwiw, this is a simple example (intended for nubies only).
>
> C:\family\ruby>cat -n test.rb
> 1 #---------------------------
> 2 #emulate c++ for (the better)
> 3 #for(int i=0; i*j/2<maxNum; i++)
> 4 # {
> 5 # //cool method stuff
> 6 # }
> 7 #---------------------------
> 8
> 9 # using normal while loop
> 10 puts "using while..."
> 11 j=20
> 12 i=0
> 13 maxnum=100
> 14 while i*j/2 < maxnum do
> 15 puts i
> 16 i+=1
> 17 end
> 18
> 19 # let's make our own for() and call it for_simple :slight_smile:
> 20 # note, there's no condition here
> 21 # we're leaving it up to yield/blocks since that
> 22 # is the ideal way, imho
> 23 def for_simple (init=0,incr=1)
> 24 i = init
> 25 loop do
> 26 yield i
> 27 i += incr
> 28 end
> 29 end
> 30
> 31 # now let's test it
> 32 puts <<TEXT
> 33 Test I.
> 34 using our own simple for()... note advantage,
> 35 we don't need to track the counter...
> 36 TEXT
> 37
> 38 for_simple do |i|
> 39 break unless i*j/2 < maxnum
> 40 puts i
> 41 end
> 42
> 43 puts <<TEXT
> 44 Test II.
> 45 here we initialize to 2 and increment by 2
> 46 again, we don't need to track the counter...
> 47 TEXT
> 48
> 49 for_simple(2,2) do |i|
> 50 break unless i*j/2 < maxnum
> 51 puts i
> 52 end
> 53
> 54 puts <<TEXT
> 55 Test III.
> 56 again, here we initialize to 200 and decrement by 20
> 57 again, we don't need to track the counter...
> 58 and note, we change keyword unless to if
> 59 ruby just simply rocks..
> 60 TEXT
> 61
> 62 for_simple(200,-20) do |i|
> 63 break if i*j/2 < maxnum
> 64 puts i
> 65 end
>
> C:\family\ruby>ruby test.rb
> using while...
> 0
> 1
> 2
> 3
> 4
> 5
> 6
> 7
> 8
> 9
> Test I.
> using our own simple for()... note advantage,
> we don't need to track the counter...
> 0
> 1
> 2
> 3
> 4
> 5
> 6
> 7
> 8
> 9
> Test II.
> here we initialize to 2 and increment by 2
> again, we don't need to track the counter...
> 2
> 4
> 6
> 8
> Test III.
> again, here we initialize to 200 and decrement by 20
> again, we don't need to track the counter...
> and note, we change keyword unless to if
> ruby just simply rocks..
> 200
> 180
> 160
> 140
> 120
> 100
> 80
> 60
> 40
> 20
>
> C:\family\ruby>
>
> Hth.
> kind regards -botp
>

Now is it possible, like in Scheme, to assign a variable to a string and
have Ruby evaluate the string? For example, f = "i*j/2". This would
allow one to make a more generic version of your methods. Ideally you
would have for_opt (i=0, f, inc=1) and have the method evaluate each of
the variables if necessary. This would allow one to copy working C code
without having to remember to do a lot of extraneous coding.