Most elegant way to do this?

Are there any more elegant, concise, pithy, and more Rubyish ways of
doing this?

def roll(number_of_dice)
sum = 0
number_of_dice.times do
sum += rand(5).next
end
sum
end

Thanks in advance!

[email protected] wrote:

Thanks in advance!

The Incredible Inevitable Inject:

def roll(number_of_dice)
(0…number_of_dice).inject(0){|m,r| rand(5)+m}
end

[email protected] wrote:

Thanks in advance!

I don’t think there’s really anything you can do to it, but I would
suggest that you add a parameter to set the sides of the dice and also
add one to the random output (if it’s the random number gen I’m thinking
of, it’ll give you 0-5 which means your dice have a blank side :stuck_out_tongue: )

-JC

On Nov 26, 5:24 pm, Alex Y. [email protected] wrote:

end

The Incredible Inevitable Inject:

def roll(number_of_dice)
(0…number_of_dice).inject(0){|m,r| rand(5)+m}
end

You missed the +1 needed to take rand(5) to 1…6 instead of 0…5.

And I personally like 1…num_dice instead of 0…num_dice. And,
finally, I sum things so often I usually have this lying around:

module Enumerable
def sum
if block_given?
inject(0){ |sum,obj| sum + yield(obj) }
else
inject(0){ |sum,obj| sum+obj }
end
end
end

which makes the solution simply:
def roll(number_of_dice)
(1…number_of_dice).sum{ rand(5)+1 }
end

In the vein of DRY code and unix tools, I strongly encourage everyone
to be on constant vigil looking for bits of code that can be
abstracted out to little atomic re-usable bits. After a while, coding
is less like carving entire models from styrofoam, and more like
snapping little Lego blocks together.

2007/11/27, Robert K. [email protected]:

There is another one, that - at least theoretically - saves some
addition efforts:

Of course I wanted to say that it /practically/ saves addition efforts
and /theoretically/ it will also save time.

Cheers

robert

2007/11/27, Phrogz [email protected]:

sum

end

The Incredible Inevitable Inject:

def roll(number_of_dice)
(0…number_of_dice).inject(0){|m,r| rand(5)+m}
end

You missed the +1 needed to take rand(5) to 1…6 instead of 0…5.

And everybody apparently missed 6 because rand(5) will yield 5
values ranging in 0…4. :-))

end

end

which makes the solution simply:
def roll(number_of_dice)
(1…number_of_dice).sum{ rand(5)+1 }
end

There is another one, that - at least theoretically - saves some
addition efforts:

require ‘enumerator’

def roll(number)
raise ArgumentError, “Negative!” if number < 0
number.to_enum(:times).inject(number) {|s,| s + rand(6)}
end

I also threw in to_enum just for the fun of it. :slight_smile:

In the vein of DRY code and unix tools, I strongly encourage everyone
to be on constant vigil looking for bits of code that can be
abstracted out to little atomic re-usable bits. After a while, coding
is less like carving entire models from styrofoam, and more like
snapping little Lego blocks together.

Absolutely!

Kind regards

robert

Phrogz wrote:

end
The Incredible Inevitable Inject:

def roll(number_of_dice)
(0…number_of_dice).inject(0){|m,r| rand(5)+m}
end

You missed the +1 needed to take rand(5) to 1…6 instead of 0…5.
Oops :slight_smile:

Robert K. wrote:

sum

end
The Incredible Inevitable Inject:

def roll(number_of_dice)
(0…number_of_dice).inject(0){|m,r| rand(5)+m}
end
You missed the +1 needed to take rand(5) to 1…6 instead of 0…5.

And everybody apparently missed 6 because rand(5) will yield 5
values ranging in 0…4. :-))

Nobody said dice have to be cubic…

Hi,
unknown wrote:

Are there any more elegant, concise, pithy, and more Rubyish ways of
doing this?

def roll(number_of_dice)
sum = 0
number_of_dice.times do
sum += rand(5).next
end
sum
end

Thanks in advance!

If you want the dice number, you should use rand(6).

How about this:

def roll(n)
eval(’+rand(6)+1’*n)
end

Regards,

Park H.

On Nov 26, 6:17 pm, [email protected] wrote:

Thanks in advance!

def sum *x
x.inject{|a,b| a+b}
end
def roll n
sum( *(1…n).map{rand(6)+1} )
end

On Nov 27, 6:26 am, William J. [email protected] wrote:

sum

end

Thanks in advance!

def sum *x
x.inject{|a,b| a+b}
end
def roll n
sum( *(1…n).map{rand(6)+1} )
end

Clever, but 3 times slower than the original (after correcting it).

On Nov 27, 2007 7:40 AM, Phrogz [email protected] wrote:

sum

And I personally like 1…num_dice instead of 0…num_dice. And,
end
I agree with this need, in Labrador you can do
an_enum.inject(:+)
and as we were nitpicking :wink:
inject(0){ |m,| m + rand(5) } #sic :wink:

R.

http://ruby-smalltalk.blogspot.com/


All truth passes through three stages. First, it is ridiculed. Second,
it is violently opposed. Third, it is accepted as being self-evident.
Schopenhauer (attr.)

On Nov 27, 8:37 am, Brian A. [email protected] wrote:

sum

The interface is “roll n” regardless of the underlying implementation,
You can make it ~10% faster (with the loss of some readability) by not
invoking next each time and just summing at the end:

def roll num_dice
sum = 0
num_dice.times { sum += rand(6) }
sum + num_dice
end

Actually make that ~12% faster with the following - just explain with
comments :slight_smile:

def roll num_dice
sum = num_dice
num_dice.times { sum += rand(6) }
sum
end

On Nov 27, 2:06 am, Robert K. [email protected] wrote:

2007/11/27, Phrogz [email protected]:

You missed the +1 needed to take rand(5) to 1…6 instead of 0…5.

And everybody apparently missed 6 because rand(5) will yield 5
values ranging in 0…4. :-))

Oh crimeny…oops. :stuck_out_tongue:

There is another one, that - at least theoretically - saves some
addition efforts:

require ‘enumerator’

def roll(number)
raise ArgumentError, “Negative!” if number < 0
number.to_enum(:times).inject(number) {|s,| s + rand(6)}
end

You know, I want to embrace to_enum, because it’s certainly
excellently powerful and abstract…but somehow I just don’t grok it.
Thanks for the reminder. Sometime I’ll have to think about it.

(I wish I could find some flaw with it, and say “no no no, what it
really should be is ____”; I just somehow basically find it confusing.)

Why be satisfied with a 10-12% increase in speed when we can have an
order of magnitude? :slight_smile:

sudo gem install rubyinline

require ‘rubygems’
require ‘inline’

module Kernel
inline do |builder|
builder.c "
int roll(int n) {
int sum = n;
while (n-- > 0) {
sum += (rand() % 6);
}
return sum;
}
"
end
end

puts roll(3)

On Nov 27, 2007 3:35 PM, Brian A. [email protected] wrote:

module Kernel
end
end

puts roll(3)

If you’re going to do overkill, do overkill. You’ve got an extra
compare in that main loop, with the check for n-- > 0. And it doesn’t
work for negative numbers. Correcting for this (untested):
int roll(int n) {
int sum = n;
if (n > 0) {
do {
sum += rand() % 6;
} while (–n);
} else if (n < 0) {
do {
sum -= rand() % 6;
} while (++n);
}
return sum;
}

Of course, this still has the problem that rand() % 6 typically return
slightly biased numbers, as RAND_MAX is usually a 2^n-1

:wink:

Eivind.

On Nov 26, 7:17 pm, [email protected] wrote:

Thanks in advance!

As others have pointed out, you need rand(6).next to get (1…6);
otherwise, it’s hard to improve on what you have here. This is a
simple, iterative mathematical function. I personally don’t think
using map, inject, etc. is more “Rubyish” in this context, just 2 to 3
times slower.

The interface is “roll n” regardless of the underlying implementation,
so you might as well make it fast.

One style improvement might be to use a one line block:

def roll num_dice
sum = 0
num_dice.times { sum += rand(6).next }
sum
end

You can make it ~10% faster (with the loss of some readability) by not
invoking next each time and just summing at the end:

def roll num_dice
sum = 0
num_dice.times { sum += rand(6) }
sum + num_dice
end

Brian A.

On 11/27/07, Eivind E. [email protected] wrote:

Of course, this still has the problem that rand() % 6 typically return
slightly biased numbers, as RAND_MAX is usually a 2^n-1

:wink:

Eivind.

hah! overkill not only on method, but also in worry. biased Nd6?
awesome! ok, that kind of made my morning.

Cameron

On Nov 27, 9:57 am, Eivind E. [email protected] wrote:

If you’re going to do overkill, do overkill. You’ve got an extra
compare in that main loop, with the check for n-- > 0.

I assume you’re just having fun, but even so, if your compiler doesn’t
optimize (n-- > 0) to be as efficient as (n–), get a new compiler.

And it doesn’t
work for negative numbers. Correcting for this (untested):

Yes, rolling a negative number of dice is precluded, it just confuses
people.

}
return sum;

}

You might want to double check that code…

Of course, this still has the problem that rand() % 6 typically return
slightly biased numbers, as RAND_MAX is usually a 2^n-1

Ok, here you have a point. The roll function won’t cut it in Las
Vegas.

On Nov 27, 11:53 am, Robert K. [email protected] wrote:

number_of_dice.times do

using map, inject, etc. is more “Rubyish” in this context, just 2 to 3
sum

I guess there is even more room for improvement by doing this:

def roll num_dice
sum = roll num_dice
num_dice.times { sum += rand(6) }
sum
end

SCNR :wink:

No apology necessary, I beat you to it :slight_smile: (I assume you meant sum =
num_dice)