Evaluate dice rolling notation strings

前端 未结 14 1448
甜味超标
甜味超标 2021-01-30 14:55

Rules

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

To

14条回答
  •  攒了一身酷
    2021-01-30 15:24

    python, 197 chars in obscured version.

    Readable version: 369 chars. No eval, straight forward parsing.

    import random
    def dice(s):
        return sum(term(x) for x in s.split('+'))
    def term(t):
        p = t.split('*')
        return factor(p[0]) if len(p)==1 else factor(p[0])*factor(p[1])
    def factor(f):
        p = f.split('d')
        if len(p)==1:
            return int(f)
        return sum(random.randint(1, int(g[1]) if g[1] else 6) for \
                   i in range(int(g[0]) if g[0] else 1))
    

    compressed version: 258 chars, single character names, abused conditional expressions, shortcut in logical expression:

    import random
    def d(s):
     return sum(t(x.split('*')) for x in s.split('+'))
    def t(p):
     return f(p[0])*f(p[1]) if p[1:] else f(p[0])
    def f(s):
     g = s.split('d')
     return sum(random.randint(1, int(g[1] or 6)) for i in range(int(g[0] or 1))) if g[1:] else int(s)
    

    obscured version: 216 chars, using reduce, map heavily to avoid "def", "return".

    import random
    def d(s):
     return sum(map(lambda t:reduce(lambda x,y:x*y,map(lambda f:reduce(lambda x,y:sum(random.randint(1,int(y or 6)) for i in range(int(x or 1))), f.split('d')+[1]),t.split('*')),1),s.split('+')))
    

    Last version: 197 chars, folded in @Brain's comments, added testing runs.

    import random
    R=reduce;D=lambda s:sum(map(lambda t:R(int.__mul__,map(lambda f:R(lambda x,y:sum(random.randint(1,int(y or 6))for i in[0]*int(x or 1)),f.split('d')+[1]),t.split('*'))),s.split('+')))
    

    Tests:

    >>> for dice_expr in ["3d6 + 12", "4*d12 + 3","3d+12", "43d29d16d21*9+d7d9*91+2*d24*7"]: print dice_expr, ": ", list(D(dice_expr) for i in range(10))
    ... 
    3d6 + 12 :  [22, 21, 22, 27, 21, 22, 25, 19, 22, 25]
    4*d12 + 3 :  [7, 39, 23, 35, 23, 23, 35, 27, 23, 7]
    3d+12 :  [16, 25, 21, 25, 20, 18, 27, 18, 27, 25]
    43d29d16d21*9+d7d9*91+2*d24*7 :  [571338, 550124, 539370, 578099, 496948, 525259, 527563, 546459, 615556, 588495]
    

    This solution can't handle whitespaces without adjacent digits. so "43d29d16d21*9+d7d9*91+2*d24*7" will work, but "43d29d16d21*9 + d7d9*91 + 2*d24*7" will not, due to the second space (between "+" and "d"). It can be corrected by first removing whitespaces from s, but this will make the code longer than 200 chars, so I'll keep the bug.

提交回复
热议问题