কমপ্লেক্স ডাইস রোলিং এক্সপ্রেশনস


23

পটভূমি

আমি কিছু বন্ধুদের সাথে নিয়মিত ডিঅ্যান্ডডি খেলি। কিছু সিস্টেম / সংস্করণগুলির জটিলতা সম্পর্কে কথা বলার সময় যখন ডাইস রোলিংয়ের বিষয়টি আসে এবং বোনাস এবং জরিমানা প্রয়োগ করা হয়, আমরা রসিকভাবে ডাইস রোলিং এক্সপ্রেশনগুলির জন্য কিছু অতিরিক্ত জটিলতা নিয়ে এসেছি। তাদের মধ্যে কিছু খুব আপত্তিজনক ছিল ( 2d6ম্যাট্রিক্স আর্গুমেন্ট 1 এর মতো সাধারণ ডাইস এক্সপ্রেশনগুলি বাড়ানো ), তবে বাকীগুলি একটি আকর্ষণীয় সিস্টেমের জন্য তৈরি করে make

চ্যালেঞ্জ

একটি জটিল পাশা এক্সপ্রেশন দেওয়া, নিম্নলিখিত নিয়ম অনুসারে এটি মূল্যায়ন এবং ফলাফল ফলাফল।

বেসিক মূল্যায়ন বিধি

  • যখনই কোনও অপারেটর একটি পূর্ণসংখ্যার প্রত্যাশা করে তবে কোনও অপরেন্ডের জন্য একটি তালিকা গ্রহণ করে, সেই তালিকার যোগফলটি ব্যবহৃত হয়
  • যখনই কোনও অপারেটর একটি তালিকা প্রত্যাশা করে তবে কোনও অপরেন্ডের জন্য একটি পূর্ণসংখ্যা গ্রহণ করে, পূর্ণসংখ্যাটি সেই সংখ্যার একটি উপাদান হিসাবে তালিকা হিসাবে বিবেচিত হয়

অপারেটর

সমস্ত অপারেটর বাইনারি ইনফিক্স অপারেটর। ব্যাখ্যার উদ্দেশ্যে, aবাম অপারেন্ড bহবে এবং ডান অপারেন্ড হবে। তালিকার স্বরলিপি উদাহরণগুলির জন্য ব্যবহৃত হবে যেখানে অপারেটরগুলি অপারেটর হিসাবে তালিকা নিতে পারে তবে প্রকৃত প্রকাশগুলি কেবলমাত্র ইতিবাচক পূর্ণসংখ্যা এবং অপারেটর নিয়ে গঠিত of

  • d: aপরিসীমাটিতে স্বাধীন ইউনিফর্ম এলোমেলো পূর্ণসংখ্যা[1, b]
    • অগ্রাধিকার: 3
    • উভয় অপারেন্ডগুলি পূর্ণসংখ্যা
    • উদাহরণ: 3d4 => [1, 4, 3],[1, 2]d6 => [3, 2, 6]
  • t: bথেকে সর্বনিম্ন মান গ্রহণ করুনa
    • অগ্রাধিকার: 2
    • aএকটি তালিকা, bএকটি পূর্ণসংখ্যা হয়
    • যদি b > len(a), সমস্ত মান ফিরে আসে
    • উদাহরণ: [1, 5, 7]t1 => [1], [5, 18, 3, 9]t2 => [3, 5],3t5 => [3]
  • T: bথেকে সর্বোচ্চ মান গ্রহণa
    • অগ্রাধিকার: 2
    • aএকটি তালিকা, bএকটি পূর্ণসংখ্যা হয়
    • যদি b > len(a), সমস্ত মান ফিরে আসে
    • উদাহরণ: [1, 5, 7]T1 => [7], [5, 18, 3, 9]T2 => [18, 9],3T5 => [3]
  • rযদি কোনো উপাদান bআছে a, ব্যবহার করছেন তাদের উপাদান reroll যাই হোক না কেন dবিবৃতি তাদের উত্পন্ন
    • অগ্রাধিকার: 2
    • উভয় অপারেশন তালিকা
    • রিরোলিং শুধুমাত্র একবারেই করা হয়, সুতরাং bফলস্বরূপ এখনও উপাদান থাকা সম্ভব
    • উদাহরণ: 3d6r1 => [1, 3, 4] => [6, 3, 4], 2d4r2 => [2, 2] => [3, 2],3d8r[1,8] => [1, 8, 4] => [2, 2, 4]
  • Rযদি কোনো উপাদান bআছে a, যারা উপাদান বারবার reroll পর্যন্ত কোন উপাদান bব্যবহার যাই হোক না কেন উপস্থিত হয়, dবিবৃতি তাদের উত্পন্ন
    • অগ্রাধিকার: 2
    • উভয় অপারেশন তালিকা
    • উদাহরণ: 3d6R1 => [1, 3, 4] => [6, 3, 4], 2d4R2 => [2, 2] => [3, 2] => [3, 1],3d8R[1,8] => [1, 8, 4] => [2, 2, 4]
  • +: যোগ করুন aএবং bএকসাথে
    • নজির: ১
    • উভয় অপারেন্ডগুলি পূর্ণসংখ্যা
    • উদাহরণ: 2+2 => 4, [2]+[2] => 4,[3, 1]+2 => 6
  • -: bথেকে বিয়োগa
    • নজির: ১
    • উভয় অপারেন্ডগুলি পূর্ণসংখ্যা
    • b সবসময় কম হবে a
    • উদাহরণ: 2-1 => 1, 5-[2] => 3,[8, 3]-1 => 10
  • .: একত্রে aএবং bএকসাথে
    • নজির: ১
    • উভয় অপারেশন তালিকা
    • উদাহরণ: 2.2 => [2, 2], [1].[2] => [1, 2],3.[4] => [3, 4]
  • _: সরানো aসমস্ত উপাদান সহ আউটপুটb
    • নজির: ১
    • উভয় অপারেশন তালিকা
    • উদাহরণ: [3, 4]_[3] => [4], [2, 3, 3]_3 => [2],1_2 => [1]

অতিরিক্ত বিধি

  • যদি একটি এক্সপ্রেশনের চূড়ান্ত মান একটি তালিকা হয় তবে এটি আউটপুট দেওয়ার আগে যোগ করা হয়
  • পদ মূল্যায়ন শুধুমাত্র ধনাত্মক পূর্ণসংখ্যা বা ধনাত্মক পূর্ণসংখ্যা তালিকা পরিণাম ডেকে আনবে - কোনো অভিব্যক্তি একটি অ-ধনাত্মক পূর্ণসংখ্যা বা অন্তত এক অ ধনাত্মক পূর্ণসংখ্যা ধারণকারী যারা মান দ্বারা প্রতিস্থাপিত হবে একটি তালিকাতে ফলাফল 1গুলি
  • প্যারেন্টিহেসগুলি শর্তাদি গোষ্ঠী করতে এবং মূল্যায়নের ক্রম নির্দিষ্ট করতে ব্যবহার করা যেতে পারে
  • অপারেটরগুলি সর্বনিম্ন অগ্রগতির সর্বাধিক অগ্রাধিকারের ভিত্তিতে মূল্যায়ন করা হয়, বাঁধা অগ্রাধিকারের ক্ষেত্রে মূল্যায়ন বাম থেকে ডানে অগ্রসর হয় (সুতরাং 1d4d4মূল্যায়ন হবে (1d4)d4)
  • তালিকাগুলিতে উপাদানগুলির ক্রম কোনও ব্যাপার নয় - এটি অপারেটরের পক্ষে পুরোপুরি গ্রহণযোগ্য যা কোনও তালিকাটিকে তার উপাদানগুলির সাথে এটি অন্য কোনও আপেক্ষিক ক্রমে ফিরিয়ে দিতে পরিবর্তন করে for
  • যে শর্তাদি মূল্যায়ন করা যায় না বা অসীম লুপের (যেমন 1d1R1বা 3d6R[1, 2, 3, 4, 5, 6]) ফলাফল হয় তা বৈধ নয়

পরীক্ষার মামলা

বিন্যাস: input => possible output

1d20 => 13
2d6 => 8
4d6T3 => 11
2d20t1 => 13
5d8r1 => 34
5d6R1 => 20
2d6d6 => 23
3d2R1d2 => 3
(3d2R1)d2 => 11
1d8+3 => 10
1d8-3 => 4
1d6-1d2 => 2
2d6.2d6 => 12
3d6_1 => 8
1d((8d20t4T2)d(6d6R1r6)-2d4+1d2).(1d(4d6_3d3)) => 61

শেষ পরীক্ষার কেস ব্যতীত সমস্তই রেফারেন্স প্রয়োগের মাধ্যমে উত্পন্ন হয়েছিল।

কাজের উদাহরণ

এক্সপ্রেশন: 1d((8d20t4T2)d(6d6R1r6)-2d4+1d2).(1d(4d6_3d3))

  1. 8d20t4T2 => [19, 5, 11, 6, 19, 15, 4, 20]t4T2 => [4, 5, 6, 11]T2 => [11, 6](পূর্ণ 1d(([11, 6])d(6d6R1r6)-2d4+1d2).(1d(4d6_3d3)):)
  2. 6d6R1r6 => [2, 5, 1, 5, 2, 3]r1R6 => [2, 5, 3, 5, 2, 3]R6 => [2, 5, 3, 5, 2, 3]( 1d([11, 6]d[2, 5, 3, 5, 2, 3]-2d4+1d2).(1d(4d6_3d3)))
  3. [11, 6]d[2, 5, 3, 5, 2, 3] => 17d20 => [1, 6, 11, 7, 2, 8, 15, 3, 4, 18, 11, 11, 1, 10, 8, 6, 11]( 1d([1, 6, 11, 7, 2, 8, 15, 3, 4, 18, 11, 11, 1, 10, 8, 6, 11]-2d4+1d2).(1d(4d6_3d3)))
  4. 2d4 => 7( 1d([1, 6, 11, 7, 2, 8, 15, 3, 4, 18, 11, 11, 1, 10, 8, 6, 11]-7+1d2).(1d(4d6_3d3)))
  5. 1d2 => 2( 1d([1, 6, 11, 7, 2, 8, 15, 3, 4, 18, 11, 11, 1, 10, 8, 6, 11]-7+2).(1d(4d6_3d3)))
  6. [1, 6, 11, 7, 2, 8, 15, 3, 4, 18, 11, 11, 1, 10, 8, 6, 11]-7+2 => 133-7+2 => 128( 1d128).(1d(4d6_3d3)))
  7. 4d6_3d3 => [1, 3, 3, 6]_[3, 2, 2] => [1, 3, 3, 6, 3, 2, 2]( 1d128).(1d[1, 3, 3, 6, 3, 2, 2]))
  8. 1d[1, 3, 3, 6, 3, 2, 2] => 1d20 => 6( 1d128).(6))
  9. 1d128 => 55( 55.6)
  10. 55.6 => [55, 6]( [55, 6])
  11. [55, 6] => 61 (সম্পন্ন)

রেফারেন্স বাস্তবায়ন

এই রেফারেন্স বাস্তবায়ন 0পরীক্ষামূলক, ধারাবাহিক আউটপুটগুলির জন্য প্রতিটি অভিব্যক্তি মূল্যায়নের জন্য একই ধ্রুবক বীজ ( ) ব্যবহার করে। এটি STDIN এ ইনপুট প্রত্যাশা করে, প্রতিটি এক্সপ্রেশন পৃথক করে নতুন লাইনের সাথে।

#!/usr/bin/env python3

import re
from random import randint, seed
from collections import Iterable
from functools import total_ordering

def as_list(x):
    if isinstance(x, Iterable):
        return list(x)
    else:
        return [x]

def roll(num_sides):
    return Die(randint(1, num_sides), num_sides)

def roll_many(num_dice, num_sides):
    num_dice = sum(as_list(num_dice))
    num_sides = sum(as_list(num_sides))
    return [roll(num_sides) for _ in range(num_dice)]

def reroll(dice, values):
    dice, values = as_list(dice), as_list(values)
    return [die.reroll() if die in values else die for die in dice]

def reroll_all(dice, values):
    dice, values = as_list(dice), as_list(values)
    while any(die in values for die in dice):
        dice = [die.reroll() if die in values else die for die in dice]
    return dice

def take_low(dice, num_values):
    dice = as_list(dice)
    num_values = sum(as_list(num_values))
    return sorted(dice)[:num_values]

def take_high(dice, num_values):
    dice = as_list(dice)
    num_values = sum(as_list(num_values))
    return sorted(dice, reverse=True)[:num_values]

def add(a, b):
    a = sum(as_list(a))
    b = sum(as_list(b))
    return a+b

def sub(a, b):
    a = sum(as_list(a))
    b = sum(as_list(b))
    return max(a-b, 1)

def concat(a, b):
    return as_list(a)+as_list(b)

def list_diff(a, b):
    return [x for x in as_list(a) if x not in as_list(b)]

@total_ordering
class Die:
    def __init__(self, value, sides):
        self.value = value
        self.sides = sides
    def reroll(self):
        self.value = roll(self.sides).value
        return self
    def __int__(self):
        return self.value
    __index__ = __int__
    def __lt__(self, other):
        return int(self) < int(other)
    def __eq__(self, other):
        return int(self) == int(other)
    def __add__(self, other):
        return int(self) + int(other)
    def __sub__(self, other):
        return int(self) - int(other)
    __radd__ = __add__
    __rsub__ = __sub__
    def __str__(self):
        return str(int(self))
    def __repr__(self):
        return "{} ({})".format(self.value, self.sides)

class Operator:
    def __init__(self, str, precedence, func):
        self.str = str
        self.precedence = precedence
        self.func = func
    def __call__(self, *args):
        return self.func(*args)
    def __str__(self):
        return self.str
    __repr__ = __str__

ops = {
    'd': Operator('d', 3, roll_many),
    'r': Operator('r', 2, reroll),
    'R': Operator('R', 2, reroll_all),
    't': Operator('t', 2, take_low),
    'T': Operator('T', 2, take_high),
    '+': Operator('+', 1, add),
    '-': Operator('-', 1, sub),
    '.': Operator('.', 1, concat),
    '_': Operator('_', 1, list_diff),
}

def evaluate_dice(expr):
    return max(sum(as_list(evaluate_rpn(shunting_yard(tokenize(expr))))), 1)

def evaluate_rpn(expr):
    stack = []
    while expr:
        tok = expr.pop()
        if isinstance(tok, Operator):
            a, b = stack.pop(), stack.pop()
            stack.append(tok(b, a))
        else:
            stack.append(tok)
    return stack[0]

def shunting_yard(tokens):
    outqueue = []
    opstack = []
    for tok in tokens:
        if isinstance(tok, int):
            outqueue = [tok] + outqueue
        elif tok == '(':
            opstack.append(tok)
        elif tok == ')':
            while opstack[-1] != '(':
                outqueue = [opstack.pop()] + outqueue
            opstack.pop()
        else:
            while opstack and opstack[-1] != '(' and opstack[-1].precedence > tok.precedence:
                outqueue = [opstack.pop()] + outqueue
            opstack.append(tok)
    while opstack:
        outqueue = [opstack.pop()] + outqueue
    return outqueue

def tokenize(expr):
    while expr:
        tok, expr = expr[0], expr[1:]
        if tok in "0123456789":
            while expr and expr[0] in "0123456789":
                tok, expr = tok + expr[0], expr[1:]
            tok = int(tok)
        else:
            tok = ops[tok] if tok in ops else tok
        yield tok

if __name__ == '__main__':
    import sys
    while True:
        try:
            dice_str = input()
            seed(0)
            print("{} => {}".format(dice_str, evaluate_dice(dice_str)))
        except EOFError:
            exit()

[1]: adbম্যাট্রিক্স আর্গুমেন্টগুলির জন্য আমাদের সংজ্ঞাটি ছিল যেখানে AdXপ্রতিটিতে অন্তর্ভুক্ত Xছিল । স্পষ্টতই এটি এই চ্যালেঞ্জের জন্য খুব অযৌক্তিক।a * bA = det(a * b)



সঙ্গে গ্যারান্টি -যে bসবসময় কম হবে চেয়ে aআমি অ ধনাত্মক পূর্ণসংখ্যা পেতে কোন উপায়, তাই দ্বিতীয় অতিরিক্ত নিয়ম অর্থহীন বলে মনে হয়। ওটিওএইচ, _খালি তালিকার ফলস্বরূপ হতে পারে যা একই ক্ষেত্রে কার্যকর মনে হয় তবে যখন পূর্ণসংখ্যার প্রয়োজন হয় তখন এর অর্থ কী? সাধারণত আমি যোগফলটি বলতে চাই 0...
খ্রিস্টান সিভর্স

@ ক্রিশ্চিয়িয়ানসিভার্স ১) আমি স্বচ্ছতার জন্য ধনাত্মক পূর্ণসংখ্যার বিষয়ে অতিরিক্ত নোট যুক্ত করেছি। 2) একটি খালি তালিকার যোগফল 0। অ-ধনাত্মক নিয়মের দ্বারা এটি হিসাবে মূল্যায়ন করা হবে 1
মেগো

ঠিক আছে, তবে মধ্যবর্তী ফলাফল হিসাবে এটি কি ঠিক আছে? তাই [1,2]_([1]_[1])তো [1,2]?
খ্রিস্টান সিভর্স

@ChristianSievers নং সেই স্থাপিত হবে [2], কারণ [1]_[1] -> [] -> 0 -> 1 -> [1]
মেগো

উত্তর:


9

পাইথন 3, 803 788 753 749 744 748 745 740 700 695 682 বাইট

exec(r'''from random import*
import re
class k(int):
 p=0;j=Xl([d(randint(1,int(b)),b)Zrange(a)]);__mul__=Xl(sorted(Y)[:b]);__matmul__=Xl(sorted(Y)[-b:]);__truediv__=Xl([d(randint(1,int(_.i)),_.i)if _==b else _ ZY]);__sub__=Xk(max(1,int.__sub__(a,b)))
 def __mod__(a,b):
  x=[]
  while x!=Y:x=Y;a=a/b
  Wl(x)
 def V:
  if b.p:p=b.p;del b.p;Wl(Y+b.l)if~-p else l([_ZY if~-(_ in b.l)])
  Wk(int.V)
 def __neg__(a):a.p+=1;Wa
def l(x):a=k(sum(x)or 1);Y=x;Wa
def d(v,i):d=k(v);d.i=i;Wd
lambda a:eval(re.sub("(\d+)","(k(\\1))",a).translate({100:".j",116:"*",84:"@",114:"/",82:"%",46:"+--",95:"+-"}))'''.translate({90:" for _ in ",89:"a.l",88:"lambda a,b:",87:"return ",86:"__add__(a,b)"}))

মিস্টার এক্সকোডারকে -5 বাইট ধন্যবাদ thanks

-5 আরও বাইট এনজিএন ধন্যবাদ

- প্রায় 40 বাইট জোনাথন ফরাসি ধন্যবাদ

ইয়াক, কি ক্লড্জ! এটি আমার kক্লাসের সমস্ত নম্বর মোড়ানোর জন্য নিয়মিত অভিব্যক্তি ব্যবহার করে এবং সমস্ত অপারেটরকে অপারেটর পাইথন বোঝে রূপান্তর করে, তারপরে kগণিতটি পরিচালনা করতে ক্লাসের যাদু পদ্ধতিগুলি ব্যবহার করে works +-এবং +--জন্য শেষে .এবং _প্রাধান্য সঠিক রাখার একটি হ্যাক হয়। তেমনি, আমি **অপারেটরটিকে ডি এর জন্য ব্যবহার করতে পারি না কারণ এটি করার ফলে 1d4d4পার্স করা হবে 1d(4d4)। পরিবর্তে, আমি সমস্ত সংখ্যা প্যারেনের একটি অতিরিক্ত সেটগুলিতে গুটিয়ে রাখি এবং করি .j, কারণ পদ্ধতি কলগুলির অপারেটরগুলির চেয়ে বেশি অগ্রাধিকার রয়েছে। শেষ লাইনটি বেনামে ফাংশন হিসাবে মূল্যায়ন করে যা প্রকাশকে মূল্যায়ণ করে।


def __mod__(a, b)... কেন মধ্যে স্থান a,এবং b?
মিঃ এক্সকোডার


@ Mr.Xcoder আমি মনে করি আপনি একটি অপ্রয়োজনীয় স্থান সরিয়ে একটি বাইট সংরক্ষণ করতে পারেন: ; __sub__। এবং সম্ভবত এখানে: lambda a,b: l(
জোনাথন ফ্রেচ 21

1
আপনি একটি exec("""...""".replace("...","..."))বিবৃতিতে আপনার পুরো কোডটি মোড়ানো এবং একটি return অক্ষর দ্বারা প্রায়শই (যেমন ) ঘটে এমন স্ট্রিংগুলি প্রতিস্থাপন করে কিছু বাইট সংরক্ষণ করতে পারেন । যাইহোক, আমার কাছে- execস্ট্রেস্টি সবসময় কিছুটা অস্বস্তিকর মনে হয় ...
জোনাথন ফ্রেচ

লাশ __mod__এবং __add__প্রয়োজন হবে না যে অনেক ইন্ডেন্ট
ngn

3

এপিএল (ডায়ালগ ক্লাসিক) , 367 বাইট

d←{(⊢⍪⍨1+?)⍉⍪⊃⍴/⊃¨+/¨⍺⍵}⋄r←{z←⊣⌿⍺⋄((m×?n)+z×~m←z∊⊣⌿⍵)⍪n←⊢⌿⍺}⋄R←{⍬≡⊃∩/⊣⌿¨⍺⍵:⍺⋄⍵∇⍨⍺r⍵}
u←{⍺[;((⊃+/⍵)⌊≢⍉⍺)↑⍺⍺⊣⌿⍺]}⋄t←⍋u⋄T←⍒u⋄A←+/,⋄S←+/,∘-⋄C←,⋄D←{⍺/⍨~⊃∊/⊣⌿¨⍺⍵}
hv←⍬⋄o'drRtT+-._'f←{8<io⍳⊃⍵:0v⊢←(¯2v),(⍎i'drRtTASCD')/¯2v}
{⊃⍵∊⎕d:v,←⊂⍪2↑⍎⍵⋄'('=⍵:h,←⍵⋄')'=⍵:h↑⍨←i-1f¨⌽h↓⍨i←+/∨\⌽h='('⋄h,←⍵⊣h↓⍨←-i⊣f¨⌽h↑⍨-i←+/\⌽≤/(1 4 4 1/⌽⍳4)[o⍳↑⍵,¨h]}¨'\d+' '.'s'&'⊢⍞
f¨⌽h1⌈+/⊣⌿⊃v

এটি অনলাইন চেষ্টা করুন!

রেফারেন্স প্রয়োগকরণের evaluate_dice()ক্রুফট এবং অবজেক্ট-ওরিয়েন্টেড ননসেন্স ছাড়াই এটি হ'ল শার্টিং ইয়ার্ড অ্যালগরিদম । hঅপারেটর এবং vমানগুলির জন্য : কেবল দুটি স্ট্যাক ব্যবহার করা হয় । পার্সিং এবং মূল্যায়ন ইন্টারলিভড।

মধ্যবর্তী ফলাফলগুলি 2 × N ম্যাট্রিক হিসাবে প্রতিনিধিত্ব করা হয় যেখানে প্রথম সারিটি এলোমেলো মান এবং দ্বিতীয় সারিতে পাশের পাশের সংখ্যা যা তাদের উত্পাদন করে। যখন ফলটি পাশা নিক্ষেপকারী "d" অপারেটর দ্বারা উত্পাদিত হয় না, তখন দ্বিতীয় সারিতে স্বেচ্ছাসেবী সংখ্যা থাকে। একটি একক এলোমেলো মান হ'ল 2 × 1 ম্যাট্রিক্স এবং এভাবে 1-উপাদান তালিকা থেকে পৃথক করা যায় ind


3

পাইথন 3: 723 722 714 711 707 675 653 665 বাইট

import re
from random import*
S=re.subn
e=eval
r=randint
s=lambda a:sum(g(e(a)))or 1
g=lambda a:next(zip(*a))
def o(m):a,o,b=m.groups();A=sorted(e(a));t=g(e(b));return str(o in"rR"and([([v,(r(1,d)*(o>"R")or choice([n+1for n in range(d)if~-(n+1in t)]))][v in t],d)for(v,d)in A])or{"t":A[:s(b)],"T":A[-s(b):],"+":[(s(a)+s(b),0)],"-":[(s(a)-s(b),0)],".":e(a)+e(b),"_":[t for t in e(a)if~-(t[0]in g(e(b)))]}[o])
def d(m):a,b=map(s,m.groups());return str([(r(1,b),b)for _ in" "*a])
p=r"(\[[^]]+\])"
def E(D):
 D,n=S(r"(\d+)",r"[(\1,0)]",D)
 while n:
  n=0
  for e in[("\(("+p+")\)",r"\1"),(p+"d"+p,d),(p+"([tTrR])"+p,o),(p+"(.)"+p,o)]:
   if n<1:D,n=S(*e,D)
 return s(D)

এন্ট্রি পয়েন্ট হয় E । এটি নিয়মিত প্রকাশগুলি পুনরাবৃত্তভাবে প্রয়োগ করে। প্রথমে এটি সমস্ত xসংখ্যাকে একটি একক তালিকার তালিকার সাথে প্রতিস্থাপন করে [(x,0)]। তারপরে প্রথম নিয়মিত এক্সপ্রেশনটি টিপলগুলির মতো অ্যারের স্ট্রিং প্রতিনিধিত্ব dকরে সমস্তকে প্রতিস্থাপন করে অপারেশন সম্পাদন করে । প্রতিটি টিপলের দ্বিতীয় উপাদানটি দ্বিতীয় অপারেন্ড হয় । তারপরে, পরবর্তী নিয়মিত প্রকাশগুলি অপারেটরগুলির প্রতিটি সম্পাদন করে। সম্পূর্ণ গণনা করা এক্সপ্রেশন থেকে প্যারেন্সকে সরিয়ে দেওয়ার জন্য একটি বিশেষ রেজেক্স রয়েছে।[(x,0)]d[(b,0)][(1,b),(2,b),(3,b)]d


3

Clojure, 731 720 বাইট

(যখন নিউলাইনগুলি সরানো হবে)

আপডেট: এর একটি সংক্ষিপ্ত বাস্তবায়ন F

(defn N[i](if(seq? i)(apply + i)i))
(defn g[i](let[L(fn[i](let[v(g i)](if(seq? v)v(list v))))R remove T take](if(seq? i)(let[[o a b :as A]i](if(some symbol? A)(case o d(repeatedly(N(g a))(fn[](inc(rand-int(N(g b))))))t(T(N(g b))(sort(g a)))T(T(N(g b))(sort-by -(g a)))r(for[i(L a)](if((set(L b))i)(nth(L a)0)i))R(T(count(L a))(R(set(L b))(for[_(range)i(L a)]i)))+(+(N(g a))(N(g b)))-(-(N(g a))(N(g b))).(into(L a)(L b))_(R(set(L b))(g a)))A))i)))
(defn F[T](if(seq? T)(if(next T)(loop[[s & S]'[_ . - + R r T t d]](let[R reverse[b a](map R(split-with(comp not #{s})(R T)))a(butlast a)](if a(cons s(map F[a b]))(recur S))))(F(first T)))T))
(defn f[i](N(g(F(read-string(clojure.string/replace(str"("i")")#"[^0-9]"" $0 "))))))

এটি চারটি প্রধান অংশ নিয়ে গঠিত:

  • N: একটি সংখ্যায় একটি তালিকা coerces
  • g: একটি বিমূর্ত সিনট্যাক্স ট্রি মূল্যায়ন (3 আইটেম সহ এস এক্সপ্রেশন)
  • F: একটি ইনফিক্স এএসটি প্রিফিক্স নোটেশনে রূপান্তর করে (এস-এক্সপ্রেশন), অপারেন্ড অর্ডার অগ্রাধিকারও প্রয়োগ করে
  • f: read-stringএকটি স্ট্রিংটিকে সংখ্যা এবং চিহ্নগুলির নেস্টেড ক্রম (ইনফিক্স এএসটি) তে রূপান্তর করতে ব্যবহার করে, ফল - নম্বরটি ফিরিয়ে এফ -> জি -> এন এর মাধ্যমে তাদের পাইপ দেয়।

আমি নিশ্চিত নই যে কীভাবে এটি পুরোপুরি পরীক্ষা করা যায়, সম্ভবত কোনও রেফারেন্স বাস্তবায়নের বিরুদ্ধে পরিসংখ্যান পরীক্ষার মাধ্যমে? কমপক্ষে এএসটি এবং এর মূল্যায়ন অনুসরণ করা তুলনামূলকভাবে সহজ।

এর থেকে এস-এক্সপ্রেশন উদাহরণ 1d((8d20t4T2)d(6d6R1r6)-2d4+1d2).(1d(4d6_3d3)):

(. (d 1 (- (d (T (t (d 8 20) 4) 2)
              (R (d 6 6) (r 1 6)))
           (+ (d 2 4)
              (d 1 2))))
   (d 1 (_ (d 4 6) (d 3 3))))

ইন্টার্নিয়েট ফলাফল এবং পরীক্ষার সাথে কম গল্ফড:

(def f #(read-string(clojure.string/replace(str"("%")")#"[^0-9]"" $0 ")))

(defn F [T]
  (println {:T T})
  (cond
    (not(seq? T))T
    (symbol?(first T))T
    (=(count T)1)(F(first T))
    1(loop [[s & S] '[_ . - + R r T t d]]
      (let[[b a](map reverse(split-with(comp not #{s})(reverse T)))
           _ (println [s a b])
           a(butlast a)]
        (cond
          a(do(println {:s s :a a :b b})(cons s(map F[a b])))
          S(recur S))))))


(->> "3d6" f F)
(->> "3d6t2" f F)
(->> "3d2R1" f F)
(->> "1d4d4" f F)
(->> "2d6.2d6" f F)
(->> "(3d2R1)d2" f F)
(->> "1d((8d20t4T2)d(6d6R1r6)-2d4+1d2).(1d(4d6_3d3))" f F)

(defn N[i](if(seq? i)(apply + i)i))

(defn g[i]
  (let[L(fn[i](let[v(g i)](if(seq? v)v(list v))))]
    (if(seq? i)
      (let[[o a b :as A] i]
        (println {:o o :a a :b b :all A})
        (if(every? number? A)(do(println{:A A})A)
           (case o
            d (repeatedly(N (g a))(fn[](inc(rand-int(N (g b))))))
            t (take(N (g b))(sort(g a)))
            T (take(N (g b))(sort-by -(g a)))
            r (for[i(L a)](if((set(L b))i)(nth(L a)0)i))
            R (take(count(g a))(remove(set(L b))(for[_(range)i(g a)]i)))
            + (+(N (g a))(N (g b)))
            - (-(N (g a))(N (g b)))
            . (into(L a)(L b))
            _ (remove(set(L b))(g a)))))
      (do(println {:i i})i))))


(g '(. (d 3 5) (d 4 3)))
(g '(. 1 (2 3)))
(g '(+ 1 (2 3)))
(g '(R (d 10 5) (d 1 3)))
(g '(T (d 5 20) 3))
(g '(t (d 5 20) 3))
(g '(d (d 3 4) 10))
(g '(d 4 3))
(g '(_ (d 4 6) (d 3 3)))

(->> "1d(4d6_3d3)" f F g)
(->> "1r6" f F g)
(->> "(8d20t4T2)d(6d6R1r6)" f F g)
(->> "(8d20t4T2)d(6d6R1r6)-2d4+1d2).(1d(4d6_3d3)" f F g)
(->> "1d((8d20t4T2)d(6d6R1r6)-2d4+1d2).(1d(4d6_3d3))" f F g))

2

পাইথন 3, 695 বাইট

import random,tatsu
A=lambda x:sum(x)or 1
H=lambda x:[[d,D(d.s)][d in x[2]]for d in x[0]]
R=lambda x:R([H(x)]+x[1:])if{*x[0]}&{*x[2]}else x[0]
class D(int):
 def __new__(cls,s):o=super().__new__(cls,random.randint(1,s));o.s = s;return o
class S:
 o=lambda s,x:{'+':[A(x[0])+A(x[2])],'-':[A(x[0])-A(x[2])],'.':x[0]+x[2],'_':[d for d in x[0]if d not in x[2]]}[x[1]]
 f=lambda s,x:{'r':H(x),'R':R(x),'t':sorted(x[0])[:A(x[2])],'T':sorted(x[0])[-A(x[2]):]}[x[1]]
 d=lambda s,x:[D(A(x[2]))for _ in' '*A(x[0])]
 n=lambda s,x:[int(x)]
 l=lambda s,x:sum(x,[])
lambda i:tatsu.parse("s=e$;e=o|t;o=e/[-+._]/t;t=f|r;f=t/[rRtT]/r;r=d|a;d=r/d/a;a=n|l|p;n=/\d+/;l='['@:','.{n}']';p='('@:e')';",i,semantics=S())

একটি দোভাষী ব্যবহার করে নির্মিত tatsu, একটি পিইজি পার্সার লাইব্রেরি। প্রথম যুক্তি tatsu.parser()হ'ল পিইজি ব্যাকরণ।

class D(ডাইয়ের জন্য) intপ্রকারভেদে নির্মিত সাবক্লাসগুলি । এটির মান একটি রোলের ফলাফল। বৈশিষ্ট্যটি .sহ'ল মরা দিকের সংখ্যা।

class S পার্সারের জন্য শব্দার্থক ক্রিয়া রয়েছে এবং দোভাষীকে প্রয়োগ করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.