Range max

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?

On Oct 11, 2007, at 9:30 PM, Marek K. 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

On Oct 11, 9:30 pm, Marek K. [email protected]
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. :slight_smile:

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 K. wrote:

What is the catch here?

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

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

You think this has anything to do with the quality of the language?..

mortee

On Oct 11, 11:11 pm, Marek K. [email protected]
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.

Morton G. wrote:

On Oct 11, 2007, at 9:30 PM, Marek K. 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.

ara.t.howard wrote:

    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.

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://codeforpeople.com/

On Oct 11, 9:55 pm, Brian A. [email protected] wrote:

What is the catch here?
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.

2007/10/12, Yossef M. [email protected]:

it uses some king of interator to find out the value of max.
The Enumerable#max method is generalized to also work for cases such

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. :slight_smile:

Kind regards

robert

On Oct 11, 2007, at 9:11 PM, Marek K. 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://codeforpeople.com/

On Oct 12, 8:56 am, Yossef M. [email protected] wrote:

What you want is something like
Actually, what you want is simply N. It’s a nonsensical request from a
troll. Using max, end, last, etc. to find the end of the range is
ridiculous since you must know the end of the range to define the
range!

Brian A. wrote:

What you want is something like

Actually, what you want is simply N. It’s a nonsensical request from a
troll. Using max, end, last, etc. to find the end of the range is
ridiculous since you must know the end of the range to define the
range!

Ehhh… it’s actually quite probable that the OP was indeed just insult

  • however, you all seem to assume that the same person provides both the
    range and wants to know its max.

If e.g. you write a method, which accepts various types of arguments,
then you can’t know in advance if it’ll be a range, array or something
else. So you have to use #max - and then one might expect that a range
(however big the span is) can compute it in constant time.

So the OP had some validity, while this still doesn’t have anything to
do with the quality of the language itself. Just one spot where the it
might possibly be enhanced a bit.

mortee

On Oct 12, 12:42 pm, mortee [email protected] wrote:

Brian A. wrote:

Actually, what you want is simply N. It’s a nonsensical request from a
troll. Using max, end, last, etc. to find the end of the range is
ridiculous since you must know the end of the range to define the
range!

Ehhh… it’s actually quite probable that the OP was indeed just insult

  • however, you all seem to assume that the same person provides both the
    range and wants to know its max.

I think you’re assuming we’re assuming :slight_smile: Rather than put words into
the OP’s mouth with respect to the scope of the range problem he’s
allegedly trying to solve, I was referring specifically to an integer
range problem only - can’t speak for everyone though.

With respect to an integer range, a combination of Range#end and
Range#exclude_end?

On Oct 12, 2007, at 7:45 PM, Brian A. wrote:

With respect to an integer range, a combination of Range#end and
Range#exclude_end?

0 … 1

we know that max != 0, so

max = 0.9?
max = 0.99?
max = 0.999?
max = 0.9999?

a @ http://codeforpeople.com/

On Oct 12, 2007, at 9:40 AM, Brian A. wrote:

Actually, what you want is simply N. It’s a nonsensical request from a
troll. Using max, end, last, etc. to find the end of the range is
ridiculous since you must know the end of the range to define the
range!

that is not true. any object can be used in a range in ruby. it
only must respond to #succ. it’s quite possible to declare classes
that worked like so

class TimeOfDay
end

noon_today = TimeOfDay 12, :today
noon_morrow = TimeOfDay 12, :tomorrow

noon_to_noon = noon_today … noon_tomorrow

p noon_to_noon.max #=> TimeOfDay< @hour=24, @minute=0, @second=0 >

in other words to construct a cycle or other sequence using a range.
and, more simply

-1 … -4

while quite valid, requires some thought as to which end is the
maximum. with pure numbers you’d say -1 (the first) but, if those
were like so

Depth(-1) … Depth(-4)

that the Depth class semantics may dictate that Depth(-4) is in fact
the max.

regards.

a @ http://codeforpeople.com/

On Oct 12, 1:25 pm, “ara.t.howard” [email protected] wrote:

On Oct 12, 2007, at 9:40 AM, Brian A. wrote:

Actually, what you want is simply N. It’s a nonsensical request from a
troll. Using max, end, last, etc. to find the end of the range is
ridiculous since you must know the end of the range to define the
range!

that is not true. any object can be used in a range in ruby. it
only must respond to #succ. it’s quite possible to declare classes
that worked like so

I’m not unfamiliar with the domain of the Range class. Let’s not get
ridiculous here; I was referring specifically to integer ranges.
Nothing unambiguates like code, eh? :slight_smile:

class Range
def max_int
raise ‘invalid range’ if self.end < self.begin
self.end - (self.exclude_end? ? 1 : 0)
end
end

On Oct 12, 9:52 pm, “ara.t.howard” [email protected] wrote:

On Oct 12, 2007, at 7:45 PM, Brian A. wrote:

With respect to an integer range, a combination of Range#end and
Range#exclude_end?

0 … 1

we know that max != 0, so

Wrong. (0…1).max_int → 0 (see code in other post)

max = 0.9?
max = 0.99?
max = 0.999?
max = 0.9999?

What the heck are you talking about? Do you really think that 0.9 or
0.99 is in the range (0…1) ?

On Oct 12, 9:59 pm, Brian A. [email protected] wrote:

that worked like so
end
Actually, I think the following would be better for those rare people
who find themselves frequently wondering what the largest int in a
range is, and would prefer O(1) instead of O(n):

class Range
alias orig_max max
def max
if ( self.begin.kind_of?(Integer) &&
self.end.kind_of?(Integer) &&
self.begin <= self.end )
self.exclude_end? ? self.end - 1 : self.end
else
orig_max
end
end
end

Now if someone can just come up with a real world example (i.e.
currently existing code in production) of Ruby code that actually
requires this, I’ll be amazed. :slight_smile:

On Oct 12, 2007, at 8:05 PM, Brian A. wrote:

0 … 1

we know that max != 0, so

Wrong. (0…1).max_int → 0 (see code in other post)

you code does not return the max, it returns the ‘end’, and
incorrectly in some cases.

any range/interval whose end > start must have size > 0. therefore
the max cannot == start. i think you are confusing the concept of
sequence with that of a range

Sequence - Wikipedia # sequence
Interval (mathematics) - Wikipedia # range

there is no constraint on ruby ranges to be either - one may use
the range to represent either. if one uses it to represent an
interval the, with an open ended (… vs …) range there is no way to
compute the max. this is a very useful property because you can use
it to do things like

f = 0.42

r = 0 … 1

if f > r.start and f < r.end

...

so, if we are talking general purpose methods, which the OP was,
Range#max cannot be written to be general purpose, even for integer
‘ranges’

max = 0.9?
max = 0.99?
max = 0.999?
max = 0.9999?

What the heck are you talking about? Do you really think that 0.9 or
0.99 is in the range (0…1) ?

yes. but it is not in the integer sequence.

regards.

a @ http://codeforpeople.com/