From: Ruby Quiz Date: 2006-01-07T03:56:47+09:00 Subject: [QUIZ] Dice Roller (#61) The three rules of Ruby Quiz: 1. Please do not post any solutions or spoiler discussion for this quiz until 48 hours have passed from the time on this message. 2. Support Ruby Quiz by submitting ideas as often as you can: http://www.rubyquiz.com/ 3. Enjoy! -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= by Matthew D Moss Time to release your inner nerd. The task for this Ruby Quiz is to write a dice roller. You should write a program that takes two arguments: a dice expression followed by the number of times to roll it (being optional, with a default of 1). So to calculate those stats for your AD&D character, you would do this: > roll.rb "3d6" 6 72 64 113 33 78 82 Or, for something more complicated: > roll.rb "(5d5-4)d(16/d4)+3" 31 [NOTE: You'll usually want quotes around the dice expression to hide parenthesis from the shell, but the quotes are not part of the expression.] The main code of roll.rb should look something like this: d = Dice.new(ARGV[0]) (ARGV[1] || 1).to_i.times { print "#{d.roll} " } The meat of this quiz is going to be parsing the dice expression (i.e., implementing Dice.new). Let's first go over the grammar, which I present in a simplified BNF notation with some notes: := + | - | * | / | ( ) | [] d | integer * Integers are positive; never zero, never negative. * The "d" (dice) expression XdY rolls a Y-sided die (numbered from 1 to Y) X times, accumulating the results. X is optional and defaults to 1. * All binary operators are left-associative. * Operator precedence: ( ) highest d * / + - lowest [NOTE: The BNF above is simplified here for clarity and space. If requested, I will make available the full BNF description I've used in my own solution, which incorporates the association and precedence rules.] A few more things... Feel free to either craft this by hand or an available lexing/parsing library. Handling whitespace between integers and operators is nice. Some game systems use d100 quite often, and may abbreviate it as "d%" (but note that '%' is only allowed immediately after a 'd').