评估骰子滚动符号字符串 [英] Evaluate dice rolling notation strings

查看:176
本文介绍了评估骰子滚动符号字符串的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

编写一个接受字符串作为参数的函数,返回 骰子表示法中的表达式的评估值, 包括加法和乘法.

Write a function that accepts string as a parameter, returning evaluated value of expression in dice notation, including addition and multiplication.

为了澄清问题,下面是EBNF对法律表达的定义:

To clear the things up, here comes EBNF definition of legal expressions:

roll ::= [positive integer], "d", positive integer
entity ::= roll | positive number
expression ::= entity { [, whitespace], "+"|"*"[, whitespace], entity }

示例输入:

  • "3d6 + 12"
  • "4 * d12 + 3"
  • "d100"

禁止使用 eval 功能或类似功能,但我鼓励 不使用这些就可以解决.欢迎再次进入.

Using eval functions, or similar, is not forbidden, but I encourage to solving without using these. Re-entrancy is welcome.

我不能提供测试用例,因为输出应该是随机的;).

I cannot provide test-cases, as output should be random ;).

设置答案的标题格式:语言,n个字符(重要注释-无eval等)

Format your answers' titles: language, n characters (important notes — no eval, etc.)

我的 ruby​​ 解决方案, 92 81个字符,使用eval:

My ruby solution, 92 81 characters, using eval:

def f s
eval s.gsub(/(\d+)?d(\d+)/i){eval"a+=rand $2.to_i;"*a=($1||1).to_i}
end

另一种 ruby​​ 解决方案,并不短(92个字符),但我发现它很有趣-它仍然使用eval,但是这次以非常有创意的方式.

Another ruby solution, not shorter (92 characters), but I find it interesting — it still uses eval but this time in quite creative way.

class Fixnum
def**b
eval"a+=rand b;"*a=self
end
end
def f s
eval s.gsub(/d/,'**')
end

推荐答案

C#类.它递归地评估加法和乘法,从左到右评估链式模具辊

C# class. It evaluates recursively for addition and multiplication, left-to-right for chained die rolls

  • 在每次通话中删除了.Replace(" ","")
  • 改为在int.TryParse上添加了.Trim()
  • 所有工作现在都通过单一方法完成
  • 如果未指定模数,则假设为6(请参阅Wiki文章)
  • 重构冗余调用以解析"d"的左侧
  • 重构不必要的if语句
  • Removed .Replace(" ","") on each call
  • Added .Trim() on int.TryParse instead
  • All work is now done in single method
  • If die face count is not specified, assumes 6 (see Wiki article)
  • Refactored redundant call to parse left side of "d"
  • Refactored unnecessary if statement

已缩小:(411字节)

Minified: (411 bytes)

class D{Random r=new Random();public int R(string s){int t=0;var a=s.Split('+');if(a.Count()>1)foreach(var b in a)t+=R(b);else{var m=a[0].Split('*');if(m.Count()>1){t=1;foreach(var n in m)t*=R(n);}else{var d=m[0].Split('d');if(!int.TryParse(d[0].Trim(),out t))t=0;int f;for(int i=1;i<d.Count();i++){if(!int.TryParse(d[i].Trim(),out f))f=6;int u=0;for(int j=0;j<(t== 0?1:t);j++)u+=r.Next(1,f);t+=u;}}}return t;}}

展开形式:

    class D
    {
        /// <summary>Our Random object.  Make it a first-class citizen so that it produces truly *random* results</summary>
        Random r = new Random();

        /// <summary>Roll</summary>
        /// <param name="s">string to be evaluated</param>
        /// <returns>result of evaluated string</returns>
        public int R(string s)
        {
            int t = 0;

            // Addition is lowest order of precedence
            var a = s.Split('+');

            // Add results of each group
            if (a.Count() > 1)
                foreach (var b in a)
                    t += R(b);
            else
            {
                // Multiplication is next order of precedence
                var m = a[0].Split('*');

                // Multiply results of each group
                if (m.Count() > 1)
                {
                    t = 1; // So that we don't zero-out our results...

                    foreach (var n in m)
                        t *= R(n);
                }
                else
                {
                    // Die definition is our highest order of precedence
                    var d = m[0].Split('d');

                    // This operand will be our die count, static digits, or else something we don't understand
                    if (!int.TryParse(d[0].Trim(), out t))
                        t = 0;

                    int f;

                    // Multiple definitions ("2d6d8") iterate through left-to-right: (2d6)d8
                    for (int i = 1; i < d.Count(); i++)
                    {
                        // If we don't have a right side (face count), assume 6
                        if (!int.TryParse(d[i].Trim(), out f))
                            f = 6;

                        int u = 0;

                        // If we don't have a die count, use 1
                        for (int j = 0; j < (t == 0 ? 1 : t); j++)
                            u += r.Next(1, f);

                        t += u;
                    }
                }
            }

            return t;
        }
    }

测试用例:

    static void Main(string[] args)
    {
        var t = new List<string>();
        t.Add("2d6");
        t.Add("2d6d6");
        t.Add("2d8d6 + 4d12*3d20");
        t.Add("4d12");
        t.Add("4*d12");
        t.Add("4d"); // Rolls 4 d6

        D d = new D();
        foreach (var s in t)
            Console.WriteLine(string.Format("{0}\t{1}", d.R(s), s));
    }

这篇关于评估骰子滚动符号字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆