ruby idiom for python's for/else while/else

G

Gergely Kontra

--nVMJ2NtxeReIH9PS
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable

Hi!

Is there a similar construct to python's:
=2E.. for x in range(2, n):
=2E.. if n % x =3D=3D 0:
=2E.. print n, 'equals', x, '*', n/x
=2E.. break
=2E.. else:
=2E.. # loop fell through without finding a factor
=2E.. print n, 'is a prime number'
=2E..=20
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

thx
Gergo
--=20
+-[ Gergely Kontra <[email protected]> http://www.mcl.hu/~kgergely ]------+
| PhD Student (Room:IB113) PGP ID: 0x66875624 Mobile:(+36 20)356 9656 |
| Budapest University of Technology and Economics ICQ# 175564914 |
+------------- "Olyan langesz vagyok, hogy poroltoval kellene jarnom!" -+

--nVMJ2NtxeReIH9PS
Content-Type: application/pgp-signature
Content-Disposition: inline

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.3 (GNU/Linux)

iD8DBQFDL0aHrl/uZWaHViQRAiDrAKDFEHzKgqVPZb4XehXaxw8bk3lbbACcCkDh
AEUPq1+ejfEWYx4+X+8fr38=
=GfHU
-----END PGP SIGNATURE-----

--nVMJ2NtxeReIH9PS--
 
W

William Morgan

Excerpts from Gergely Kontra's mail of 19 Sep 2005 (CDT):
Is there a similar construct to python's:

... for x in range(2, n):
... if n % x == 0:
... print n, 'equals', x, '*', n/x
... break
... else:
... # loop fell through without finding a factor
... print n, 'is a prime number'
...

I don't think there's a direct idiom. I'd write this in Ruby as:

(2...10).each do |n|
fac = (2...n).find { |x| n % x == 0 }
if fac
puts "#{n} equals #{fac} * #{n / fac}"
else
puts "#{n} is a prime number"
end
end

This is much clearer IMO.
 
J

Jeremy Tregunna

Hi!

Is there a similar construct to python's:

... for x in range(2, n):
... if n % x == 0:
... print n, 'equals', x, '*', n/x
... break
... else:
... # loop fell through without finding a factor
... print n, 'is a prime number'
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

Directly, yes; though hardly anybody writes code this way (at least
I've never seen anybody write something like this, like how I'm about
to give it to you). I'd see William Morgan's message for a better
suggestion.

for n in (2..10) do
for x in (2..n) do
if n % x == 0
puts "#{n} equals #{x} * #{n/x}"
break
else
puts "#{n} is a prime number"
end
end
end

--
Jeremy Tregunna
(e-mail address removed)

"If debugging is the process of removing bugs, then programming must be
the process of putting them in." --Dykstra
 
J

Joe Van Dyk

Excerpts from Gergely Kontra's mail of 19 Sep 2005 (CDT):
=20
I don't think there's a direct idiom. I'd write this in Ruby as:
=20
(2...10).each do |n|
fac =3D (2...n).find { |x| n % x =3D=3D 0 }
if fac
puts "#{n} equals #{fac} * #{n / fac}"
else
puts "#{n} is a prime number"
end
end
=20
This is much clearer IMO.

Meh, I think the Python version is much clearer. Each to his own, I guess.
 
D

David A. Black

Hi --

Directly, yes; though hardly anybody writes code this way (at least I've
never seen anybody write something like this, like how I'm about to give it
to you). I'd see William Morgan's message for a better suggestion.

for n in (2..10) do
for x in (2..n) do

You'd want the ... range operator, so as to exclude the upper limit.
if n % x == 0
puts "#{n} equals #{x} * #{n/x}"
break
else
puts "#{n} is a prime number"
end
end
end

Have you run it? :) It doesn't work the same way; it prints
"...prime number" for *every* time a match isn't found, until a match
is found. So, for example, you get:

7 is a prime number # printed 5 times (2,3,4,5,6)
8 equals 2 * 4
9 is a prime number
9 equals 3 * 3


David
 
A

Ara.T.Howard

Hi!

Is there a similar construct to python's:

... for x in range(2, n):
... if n % x == 0:
... print n, 'equals', x, '*', n/x
... break
... else:
... # loop fell through without finding a factor
... print n, 'is a prime number'
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

i would probably use catch/throw:

harp:~ > cat a.rb
(2 ... 10).each do |n|
x = catch('x'){(2 ... n).each{|x| throw 'x', x if n % x == 0}; nil}
if x
puts "#{ n } = #{ n } * #{ x }/#{ n }"
else
puts "#{ n } is prime"
end
end


harp:~ > ruby a.rb
2 is prime
3 is prime
4 = 4 * 2/4
5 is prime
6 = 6 * 2/6
7 is prime
8 = 8 * 2/8
9 = 9 * 3/9

cheers.

-a
--
===============================================================================
| email :: ara [dot] t [dot] howard [at] noaa [dot] gov
| phone :: 303.497.6469
| Your life dwells amoung the causes of death
| Like a lamp standing in a strong breeze. --Nagarjuna
===============================================================================
 
W

why the lucky stiff

William said:
Excerpts from Gergely Kontra's mail of 19 Sep 2005 (CDT):



I don't think there's a direct idiom. I'd write this in Ruby as:

(2...10).each do |n|
fac = (2...n).find { |x| n % x == 0 }
if fac
puts "#{n} equals #{fac} * #{n / fac}"
else
puts "#{n} is a prime number"
end
end

This is much clearer IMO.
Yeah, this isn't any clearer, but here's one that demonstrates the
possibilities in tying iterators and conditionals together. It works
because `break' causes the iterator to return nil.

for n in 2...10
puts "#{ n } is a prime number" if
for x in 2...n
if n % x == 0
puts "#{ n } equals #{ x }*#{ n/x }"
break
end
end
end

_why
 
D

David A. Black

Hi --

Yeah, this isn't any clearer, but here's one that demonstrates the
possibilities in tying iterators and conditionals together. It works because
`break' causes the iterator to return nil.

for n in 2...10
puts "#{ n } is a prime number" if
for x in 2...n
if n % x == 0
puts "#{ n } equals #{ x }*#{ n/x }"
break
end
end
end

I know I'm wandering into the golf realm, rather than the clarity
realm, but just for fun:

for n in 2...10
puts "#{ n } is a prime number" if
for x in 2...n
break puts("#{ n } equals #{ x }*#{ n/x }") if n % x == 0
end
end


David
 
B

Brian Mitchell

Directly, yes; though hardly anybody writes code this way (at least
I've never seen anybody write something like this, like how I'm about
to give it to you). I'd see William Morgan's message for a better
suggestion.

# I hate for loops

2.upto(10) do |n| # was =3D> for n in (2..10) do
2.upto(n) do |x| # was =3D> for x in (2..n) do
if n % x =3D=3D 0
puts "#{n} equals #{x} * #{n/x}"
break
else
puts "#{n} is a prime number"
end
end
end

Though, I think this is broken... check the output.
--
Jeremy Tregunna
(e-mail address removed)

"If debugging is the process of removing bugs, then programming must be
the process of putting them in." --Dykstra

I still think lists are the nicest way to go about this. It could be
much improved but this is shorter:
(2..10).select {|n| (2..n).select {|x| n % x =3D=3D 0 and n !=3D x }.empty?=
}

Brian,
 
D

Devin Mullins

Here's another:

(2...10).each do |n|
unless (2...n).any? do |x|
if n % x == 0
puts "#{n} equals #{x} * #{n/x}"
true
end #else nil
end
puts "#{n} is a prime number"
end
end

But, really, I'd rather write it like William Morgan did.

Devin
 
E

Eric Mahurin

--- why the lucky stiff said:
William Morgan wrote:
=20
Yeah, this isn't any clearer, but here's one that
demonstrates the=20
possibilities in tying iterators and conditionals together.=20
It works=20
because `break' causes the iterator to return nil.
=20
for n in 2...10
puts "#{ n } is a prime number" if
for x in 2...n
if n % x =3D=3D 0
puts "#{ n } equals #{ x }*#{ n/x }"
break
end
end
end
=20
_why


This is annoying - builtin loops and "loop" returns nil whereas
many of the object method loops (for..in is just the each
method) return the object. Using a builtin loop, you can do
something like this to get something much closer to python's
while/else (becomes while/or in ruby):

(2...10).each do |n|
x =3D 2
while x<n
if n % x =3D=3D 0
puts "#{ n } equals #{ x }*#{ n/x }"
break(x)
end
x +=3D 1
end or=20
puts "#{ n } is a prime number"
end

I think that's the closest your going to get to python's
while/else. You have the use the opposite polarity for the for
loop as why demonstrated. One of my RCR's is about this
inconsistency. I think all of the loop methods should return
nil by default (with break(ret) causing it to return something
else).




=09
__________________________________=20
Yahoo! Mail - PC Magazine Editors' Choice 2005=20
http://mail.yahoo.com
 
W

William James

Brian said:
# I hate for loops

2.upto(10) do |n| # was => for n in (2..10) do
2.upto(n) do |x| # was => for x in (2..n) do

Though, I think this is broken... check the output.


I still think lists are the nicest way to go about this. It could be
much improved but this is shorter:
(2..10).select {|n| (2..n).select {|x| n % x == 0 and n != x }.empty? }

Brian,

(2...50).select{|n|(2..Math.sqrt(n).to_i).select{|x|n % x == 0}.empty?}
-->
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
 
P

Pit Capitain

William said:
...
(2...50).select{|n|(2..Math.sqrt(n).to_i).select{|x|n % x == 0}.empty?}
-->
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

Should be a little bit more efficient:

(2...50).reject{|n|(2..Math.sqrt(n)).find{|x|n % x == 0}}

It's not what the OP wanted, though.

Regards,
Pit
 
B

Brian Mitchell

William said:
...
(2...50).select{|n|(2..Math.sqrt(n).to_i).select{|x|n % x =3D=3D 0}.emp= ty?}
-->
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

Should be a little bit more efficient:

(2...50).reject{|n|(2..Math.sqrt(n)).find{|x|n % x =3D=3D 0}}

It's not what the OP wanted, though.

Regards,
Pit

Yeah. I just thought I would post it. Mostly equivalent to what he was
doing but quite different in what tools were used. Yours is much more
elegant either way.

If I was serious about the prime numbers I would have built a
quadratic sieve of some sort. I also hate for-loops (in most cases).
;)

Brian.
 
P

Pit Capitain

Gergely Kontra said:
Hi!

Is there a similar construct to python's:

... for x in range(2, n):
... if n % x == 0:
... print n, 'equals', x, '*', n/x
... break
... else:
... # loop fell through without finding a factor
... print n, 'is a prime number'
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

Almost identical, but not necessarily the Ruby way:

for n in 2 ... 10
for x in 2 ... n
if n % x == 0
puts "#{n} equals #{x} * #{n/x}"
break
end
end and puts "#{n} is a prime number"
end

Regards,
Pit
 
M

Michel Martens

I think that's the closest your going to get to python's
while/else. You have the use the opposite polarity for the for
loop as why demonstrated. One of my RCR's is about this
inconsistency. I think all of the loop methods should return
nil by default (with break(ret) causing it to return something
else).

Agree.


Michel.
 
D

Devin Mullins

Pit said:
(2...50).reject{|n|(2..Math.sqrt(n)).find{|x|n % x == 0}}

It's not what the OP wanted, though.

include Math
primes = (2...10).map{|n|(2..sqrt(n)).find{|x|n % x == 0}}
primes.each_with_index do |x,n|
n += 2
if x then puts "#{n} equals #{x} * #{n/x}"
else puts "#{n} is a prime number" end
end
__END__

It is now.

Or, for readability's sake:

include Math
primes = (2...10).map{|n|[n,(2..sqrt(n)).find{|x|n % x == 0}]}
primes.each do |n,x|
if x then puts "#{n} equals #{x} * #{n/x}"
else puts "#{n} is a prime number" end
end
__END__

So, no, there may not be an exact equivalent to for/else, but as with
interface definitions in Python/Ruby, you generally find that the need
isn't there like it is in the other language. In Java, types are
staticly declared, and mixins are nonexistent, making interfaces very
important. In Python, there's a difference between statements and
expressions (IIUC), making special iterator constructs like for/else
important. IOW, it shouldn't be considered a fault of Ruby's that it
doesn't include that construct -- it doesn't need it.

Devin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top