From: Paul Novak Date: 2006-01-10T01:00:44+09:00 Subject: Re: [QUIZ.SOLUTION] Dice Roller (#61) We don't need no steenking leexer/parsers On 1/9/06, Kroeger, Simon (ext) 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 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. > > > > > >