Write a function that accepts string as a parameter, returning evaluated value of expression in dice notation, including addition and multiplication.
To
Ruby, 166 characters, no eval
In my opinion quite elegant ;).
def g s,o=%w{\+ \* d}
o[a=0]?s[/#{p=o.pop}/]?g(s.sub(/(\d+)?\s*(#{p})\s*(\d+)/i){c=$3.to_i
o[1]?($1||1).to_i.times{a+=rand c}+a:$1.to_i.send($2,c)},o<
Deobfuscated version + comments:
def evaluate(string, opers = ["\\+","\\*","d"])
if opers.empty?
string
else
if string.scan(opers.last[/.$/]).empty? # check if string contains last element of opers array
# Proceed to next operator from opers array.
opers.pop
evaluate(string, opers)
else # string contains that character...
# This is hard to deobfuscate. It substitutes subexpression with highest priority with
# its value (e.g. chooses random value for XdY, or counts value of N+M or N*M), and
# calls recursively evaluate with substituted string.
evaluate(string.sub(/(\d+)?\s*(#{opers.last})\s*(\d+)/i) { a,c=0,$3.to_i; ($2 == 'd') ? ($1||1).to_i.times{a+=rand c}+a : $1.to_i.send($2,c) }, opers)
end
end
end