[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

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

Kroeger, Simon (ext)

1/9/2006 2:20:00 PM

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


1 Answer

Paul Novak

1/9/2006 4:01:00 PM

0

On 1/9/06, Kroeger, Simon (ext) <simon.kroeger.ext@siemens.com> wrote:
> 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.


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