From: Christian Neukirchen Date: 2006-01-13T00:22:30+09:00 Subject: Re: [QUIZ.SUMMARY] Dice Roller (#61) Matthew Moss writes: > First off we have the random number generation; most solutions had this or a > very similar variant. So the call 3.d(6) will roll and accumulate three > six-sided dice, and the expression 3.d(6) is almost a valid dice expression. > It is in Christian's initialization method that dice expressions are turned > into Ruby expressions: > > def initialize(dice) > @src = dice.gsub(/d(%|00)(\D|$)/, 'd100\2'). > gsub(/d(\d+)/, 'd(\1)'). > gsub(/(\d+|\))d/, '\1.d'). > gsub(/\d+/) { $&.gsub(/^0+/, '') } > > @dice = eval "lambda { #@src }" > end > > (I've left out a bit of error checking; see the full solution to see > everything.) The first substitution fixes up percentage and double-zero > values as 100. The second turns 'd' as a binary operator into 'd' as a > method call. The third substitution provides the default dice count of 1 > if it wasn't specified. And the last substitution removes leading zeroes of > integers; this last substitution prevents the Ruby from interpreting values > as octal. The third substitution doesn't provide a default count (Dice#d does that), instead, it converts 2d(6) to 2.d(6). > The morphed express is saved away in a lambda, which allows Christian to > reevaluate the expression repeatedly without performing those substitutions > every time roll is called. I could have evaluated @src each time without substituting anew, but a lambda only makes it need to *parse* once. Thanks for the nice writeup, -- Christian Neukirchen http://chneukirchen.org