[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

range max

Marek Kasperkiewicz

10/12/2007 1:30:00 AM

If i try this
puts (1..10).max
it runs fine.
If i try this
puts (1..100000000).max
It is extremely slow. Instead of using straight math max= 100000000-1
it uses some king of interator to find out the value of max.
What is the catch here?
--
Posted via http://www.ruby-....

30 Answers

Morton Goldberg

10/12/2007 2:06:00 AM

0

On Oct 11, 2007, at 9:30 PM, Marek Kasperkiewicz wrote:

> If i try this
> puts (1..10).max
> it runs fine.
> If i try this
> puts (1..100000000).max
> It is extremely slow. Instead of using straight math max= 100000000-1
> it uses some king of interator to find out the value of max.
> What is the catch here?

I'm afraid that's the way the Enumerable mixin works.

There is an old saying: if hitting yourself on the head with hammer
hurts, just stop. I think that applies in this case.

Regards, Morton

Brian Adkins

10/12/2007 2:55:00 AM

0

On Oct 11, 9:30 pm, Marek Kasperkiewicz <m.kasperkiew...@gmail.com>
wrote:
> If i try this
> puts (1..10).max
> it runs fine.
> If i try this
> puts (1..100000000).max
> It is extremely slow. Instead of using straight math max= 100000000-1
> it uses some king of interator to find out the value of max.
> What is the catch here?

Well, one advantage of (1..N).max compared to your 'straight math'
method is the former provides the correct answer and the latter does
not. :)

However, for efficiency, if for some reason you don't want to simply
use max = N, you'll find max = (1..N).end is much faster than max =
(1..N).max since it doesn't look at each element in the range.

The Enumerable#max method is generalized to also work for cases such
as max = [1,10,100,10,1].max

Marek Kasperkiewicz

10/12/2007 3:11:00 AM

0

Morton Goldberg wrote:
> On Oct 11, 2007, at 9:30 PM, Marek Kasperkiewicz wrote:
>
>> If i try this
>> puts (1..10).max
>> it runs fine.
>> If i try this
>> puts (1..100000000).max
>> It is extremely slow. Instead of using straight math max= 100000000-1
>> it uses some king of interator to find out the value of max.
>> What is the catch here?
>
> I'm afraid that's the way the Enumerable mixin works.
>
> There is an old saying: if hitting yourself on the head with hammer
> hurts, just stop. I think that applies in this case.
>
> Regards, Morton


thanks Morton,
I thought ruby supposed to be better than Perl and Python combined, but
I can see that's not the case yet.
--
Posted via http://www.ruby-....

Brian Adkins

10/12/2007 3:34:00 AM

0

On Oct 11, 11:11 pm, Marek Kasperkiewicz <m.kasperkiew...@gmail.com>
wrote:
> thanks Morton,
> I thought ruby supposed to be better than Perl and Python combined, but
> I can see that's not the case yet.

Congratulations, you found the Achilles heel of Ruby! We try to keep
it a secret, but the dreaded (1..N).max issue will undoubtedly keep
Ruby from realizing its true potential. From what I can tell from your
postings, I'd say you'll probably prefer Perl over Python - best
wishes.

mortee

10/12/2007 3:34:00 AM

0

ara.t.howard

10/12/2007 3:49:00 AM

0


On Oct 11, 2007, at 9:11 PM, Marek Kasperkiewicz wrote:

> thanks Morton,
> I thought ruby supposed to be better than Perl and Python combined,
> but
> I can see that's not the case yet.

cfp:~ > cat a.rb
class Lang < String
class ::NilClass
def succ() Lang('perl') end
end

def succ
Lang(
case self
when /perl/i then 'python'
when /python/i then 'ruby'
else super
end
)
end

def <=> other
case other
when /ruby/i then match('ruby') ? 0 : -1
else super
end
end
end
def Lang(*a, &b) Lang.new(*a, &b) end


language = nil

list = [] and 3.times{ list << list.last.succ }

p list

p list.max, list.reverse.max, list.sort_by{ rand }.max


cfp:~ > ruby a.rb
["perl", "python", "ruby"]
"ruby"
"ruby"
"ruby"


a @ http://codeforp...
--
we can deny everything, except that we have the possibility of being
better. simply reflect on that.
h.h. the 14th dalai lama




Joel VanderWerf

10/12/2007 4:38:00 AM

0

ara.t.howard wrote:
> class Lang < String
> class ::NilClass
> def succ() Lang('perl') end
> end
>
> def succ
> Lang(
> case self
> when /perl/i then 'python'
> when /python/i then 'ruby'
> else super
> end
> )
> end
...
> end
> def Lang(*a, &b) Lang.new(*a, &b) end

nil.succ.succ.succ.succ
=> "rubz"


Is this the new name for ruby 2.0, instead of rite?

Well, I have to say it kinda rubz off on you after a while.

--
vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407

ara.t.howard

10/12/2007 4:43:00 AM

0


On Oct 11, 2007, at 10:37 PM, Joel VanderWerf wrote:

> Is this the new name for ruby 2.0, instead of rite?

shhh. don't tell!

a @ http://codeforp...
--
we can deny everything, except that we have the possibility of being
better. simply reflect on that.
h.h. the 14th dalai lama




Yossef Mendelssohn

10/12/2007 12:57:00 PM

0

On Oct 11, 9:55 pm, Brian Adkins <lojicdot...@gmail.com> wrote:
> On Oct 11, 9:30 pm, Marek Kasperkiewicz <m.kasperkiew...@gmail.com>
> wrote:
>
> > If i try this
> > puts (1..10).max
> > it runs fine.
> > If i try this
> > puts (1..100000000).max
> > It is extremely slow. Instead of using straight math max= 100000000-1
> > it uses some king of interator to find out the value of max.
> > What is the catch here?
>
> Well, one advantage of (1..N).max compared to your 'straight math'
> method is the former provides the correct answer and the latter does
> not. :)
>
> However, for efficiency, if for some reason you don't want to simply
> use max = N, you'll find max = (1..N).end is much faster than max =
> (1..N).max since it doesn't look at each element in the range.
>
> The Enumerable#max method is generalized to also work for cases such
> as max = [1,10,100,10,1].max

I was thinking Range#last, but that has the same problem as Range#end
(probably one is an alias for the other).

(1..10).last (or end) => 10
(1..10).max => 10

(1...10).last (or end) => 10
(1...10).max => 9

What you want is something like

class Range
def quick_max
last - (exclude_end? ? 1 : 0)
end
end

Of course, if you're not using Fixnums, this is wrong. Maybe if
classes defined prec (instead of only succ), this could be easy.


--
-yossef


Robert Klemme

10/12/2007 2:42:00 PM

0

2007/10/12, Yossef Mendelssohn <ymendel@pobox.com>:
> On Oct 11, 9:55 pm, Brian Adkins <lojicdot...@gmail.com> wrote:
> > On Oct 11, 9:30 pm, Marek Kasperkiewicz <m.kasperkiew...@gmail.com>
> > wrote:
> >
> > > If i try this
> > > puts (1..10).max
> > > it runs fine.
> > > If i try this
> > > puts (1..100000000).max
> > > It is extremely slow. Instead of using straight math max= 100000000-1
> > > it uses some king of interator to find out the value of max.
> > > What is the catch here?
> >
> > Well, one advantage of (1..N).max compared to your 'straight math'
> > method is the former provides the correct answer and the latter does
> > not. :)
> >
> > However, for efficiency, if for some reason you don't want to simply
> > use max = N, you'll find max = (1..N).end is much faster than max =
> > (1..N).max since it doesn't look at each element in the range.
> >
> > The Enumerable#max method is generalized to also work for cases such
> > as max = [1,10,100,10,1].max
>
> I was thinking Range#last, but that has the same problem as Range#end
> (probably one is an alias for the other).
>
> (1..10).last (or end) => 10
> (1..10).max => 10
>
> (1...10).last (or end) => 10
> (1...10).max => 9
>
> What you want is something like
>
> class Range
> def quick_max
> last - (exclude_end? ? 1 : 0)
> end
> end
>
> Of course, if you're not using Fixnums, this is wrong. Maybe if
> classes defined prec (instead of only succ), this could be easy.

I believe not. #max *has* to use <=> for a proper result. Although it
might be common that <=> and #succ represent the same ordering this is
not required. Actually there is a pretty straightforward example:

irb(main):001:0> ("a".."aa").last
=> "aa"
irb(main):002:0> ("a".."aa").max
=> "z"
irb(main):003:0> puts ("a".."aa").to_a
a
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
y
z
aa
=> nil

There is no optimization that works for all and I guess that's the
reason why Matz did not bother to provide Range#max and Enumerable#max
is used instead. And this has necessarily O(n). After all: if you
are smart enough to use Ruby then you are probably also smart enough
to not use #max on an integer range. :-)

Kind regards

robert