[QUIZ.SOLUTION] Dice Roller (#61) We don't need no steenking leexer/parsers

Hi,

first: you don't need the 'to_a'

second:

···

---------------------------------------
(0..5).inject{|x,y| print y, ' '}
puts

(1..5).inject(0){|x,y| print y, ' '}
puts
---------------------------------------
output:

1 2 3 4 5
1 2 3 4 5

If you provide no parameter to inject it will give
you the first item of the enumerable as x.

cheers

Simon

-----Original Message-----
From: Paul Novak [mailto:novakps@gmail.com]
Sent: Monday, January 09, 2006 3:04 PM
To: ruby-talk ML
Subject: Re: [QUIZ.SOLUTION] Dice Roller (#61) We don't need
no steenking leexer/parsers

No, the mis-understanding is all mine. You are right, otherwise it
will include an extra roll. It should be:
(1..self).to_a.inject(0){|x,y| x + rand(sides)}+self

Further proof of the value of good unit tests. (Since (1..1).to_a
returns a single-member array, you need to provide inject with an
initial value to make it work.)

Regards,

Paul.

On 1/9/06, Gregory Seidman <gsslist+ruby@anthropohedron.net> wrote:

> } # roll the dice
> } (0..self).to_a.inject{|x,y| x + rand(sides)}+self
>
> I think I may be misunderstanding something here. You use
0..self, when I
> would think it would have to be either 0...self or 1..self
to get the right
> number of rolls. Am I off? In my solution I used 1..self in
much the same
> way.

Hi,

first: you don't need the 'to_a'

Excellent! Less typing, and more importantly, less to parse when reading.

second:
---------------------------------------
(0..5).inject{|x,y| print y, ' '}
puts

(1..5).inject(0){|x,y| print y, ' '}
puts
---------------------------------------
output:

1 2 3 4 5
1 2 3 4 5

If you provide no parameter to inject it will give
you the first item of the enumerable as x.

That is true when you are using that first item, but for the dice
roll, we do not want the value of x in our accumulator, we are just
using length of the range to control the number of rolls.

In fact, maybe my original version was not a bug after all. Look at
these simplified statements:

irb(main):041:0> (0..2).inject{|x,y|x+2}
=> 4
irb(main):042:0> (1..2).inject(0){|x,y|x+2}
=> 4

I looks like the first example above walks through [0,1,2] and calls
the x + 2 code block two times:
first time x=0 and y = 1, returns 2
second time x = 2 (accumulated from last time) and y=2, returns 4

The second one takes [1,2] and also calls the x + 2 code block twice.
first time x=0 (this time from the initialization value), y = 1, returns 2
second time x=2 and y = 2, returns 4

Ruby doc says this is because the "second form uses the first element
of the collection as a the initial value (and skips that element while
iterating)."

I think that answers Greg's question too.

···

On 1/9/06, Kroeger, Simon (ext) <simon.kroeger.ext@siemens.com> wrote:

> No, the mis-understanding is all mine. You are right, otherwise it
> will include an extra roll. It should be:
> (1..self).to_a.inject(0){|x,y| x + rand(sides)}+self
>
> Further proof of the value of good unit tests. (Since (1..1).to_a
> returns a single-member array, you need to provide inject with an
> initial value to make it work.)
>
> Regards,
>
> Paul.
>
>
> On 1/9/06, Gregory Seidman <gsslist+ruby@anthropohedron.net> wrote:
>
> > } # roll the dice
> > } (0..self).to_a.inject{|x,y| x + rand(sides)}+self
> >
> > I think I may be misunderstanding something here. You use
> 0..self, when I
> > would think it would have to be either 0...self or 1..self
> to get the right
> > number of rolls. Am I off? In my solution I used 1..self in
> much the same
> > way.
>
>