2010-04-15 9 views
6

में एक कस्टम गणित अभिव्यक्ति का मूल्यांकन कैसे करें मैं अजगर रोलिंग पार्सर (स्निपर यदि आपको जरूरी है) लिख रहा हूं। असल में, मैं मानक गणित के मूल्यांकन का उपयोग लेकिन 'प' ऑपरेटर जोड़ना चाहते हैं:,पायथन

#xdy 
sum = 0 
for each in range(x): 
    sum += randInt(1, y) 
return sum 

ताकि उदाहरण के लिए, 1d6 + 2D6 + 2d6-72 + 4d100 = (5) + (1 + 1) + (6 + 2) -72+ (5 + 3 9 + 38 + 59) = 84

मैं सभी 'डी' को योग के साथ बदलने और फिर eval का उपयोग करने के लिए regex का उपयोग कर रहा था, लेकिन मेरे regex कोष्ठक से निपटने के दौरान अलग हो गया दोनों ओर। क्या मेरे अपने रिकर्सिव पार्सिंग को लागू करने के बजाय इसके बारे में जाने का कोई तेज तरीका है? शायद एक ऑपरेटर को eval जोड़ने के लिए?

संपादित करें: मुझे एक बुरा उदाहरण दिया गया है, क्योंकि उपर्युक्त उदाहरण मेरे वर्तमान संस्करण के साथ काम करता है। मैं जो खोज रहा हूं उसका मूल्यांकन करने का कोई तरीका है, (5+ (6 डी 6)) डी (7-2 * (1 डी 4))।
"अलग हो गए" द्वारा, मेरा मतलब था कि मेरी वर्तमान regex अभिव्यक्ति विफल रही। मैं अपनी विफलता के बारे में बहुत अस्पष्ट हूं, भ्रम के लिए खेद है। यहाँ मेरे वर्तमान कोड है:

def evalDice(roll_matchgroup): 
    roll_split = roll_matchgroup.group('roll').split('d') 
    print roll_split 
    roll_list = [] 

    for die in range(int(roll_split[0])): 
     roll = random.randint(1,int(roll_split[1])) 
     roll_list.append(roll) 

def EvalRoll(roll): 
    if not roll: return 0 
    rollPattern = re.compile('(?P<roll>\d*d\d+)') 
    roll_string = rollPattern.sub(evalDice, roll.lower()) 
इस के लिए

"(1d6 4) D100" यहां तक ​​कि, "1d6 + 4d100" बस ठीक काम करता है, लेकिन या "1d6 + 4d (100)" विफल रहता है।

+0

क्या आप हमें दिखा सकते हैं कि आपने क्या प्रयास किया है और यह कैसे विफल हुआ? –

+0

बस एक पुनरावर्ती सहायक समारोह बनाने के लिए समाप्त हो गया। पूरी सहायताके लिए शुक्रिया! – taynaron

उत्तर

5

पायथन आपको ब्रांड नए ऑपरेटरों को लिखने नहीं देता है, और आप नियमित भाषा के साथ कोष्ठक नहीं कर सकते हैं। आपको एक रिकर्सिव वंश पार्सर लिखना होगा। यद्यपि यह आपके पासा-रोलिंग भाषा के लिए बहुत आसान होना चाहिए।

वैकल्पिक रूप से, आप मौजूदा पायथन ऑपरेटर को अपनाने और पाठ को एएसटी में बदलने के लिए पायथन पार्सिंग टूल का उपयोग कर सकते हैं।

+0

मुझे लगता है कि माता-पिता एक प्रदर्शनशील मध्यवर्ती परिणाम के रूप में थे, डीएसएल का हिस्सा नहीं। लेखन '1 डी 6 + 2 डी 6 + 2 डी 6-72 + 4 डी 100 = 84' स्पष्टीकरणपूर्ण नहीं होगा। हालांकि, रिक वंश के सुझाव के लिए +1। –

+0

फिर मैं उलझन में हूं। ओपी के "रेगेक्स [पतन] कोष्ठक से निपटने के दौरान अलग क्यों किया गया"? –

+1

मुझे लगता है कि मैं क्षमा से ज्यादा अस्पष्ट था। उपर्युक्त उदाहरण ठीक काम करता है। मेरा मतलब यह था कि यदि आप डी के किसी भी तरफ ब्रांड्स डालते हैं (जैसे (4 + 2) डी 6) दुभाषिया मूल्यांकन करने में संभाल नहीं सकता है। – taynaron

6

आप re.sub के साथ callback function का उपयोग कर सकते हैं। जब आप लिंक का पालन करें, साथ

import re 
import random 

def xdy(matchobj): 
    x,y=map(int,matchobj.groups()) 
    s = 0 
    for each in range(x): 
     s += random.randint(1, y) 
    return str(s) 
s='1d6+2d6+2d6-72+4d100' 
t=re.sub('(\d+)d(\d+)',xdy,s) 
print(t) 
# 5+10+8-72+197 
print(eval(t)) 
# 148 
0

यह eval का उपयोग करता है, जो वास्तव में बहुत भयानक है "अगर repl एक समारोह है ...", लेकिन यहाँ तुम जाओ

>>> x = '1d6+2d6+2d6-72+4d100' 
>>> eval(re.sub(r'(\d+)d(\d+)',r'sum((random.randint(1,x) for x in \1 * [\2]))', x)) 
शुरुआत पैरा करने के लिए नीचे खोज

कुछ देने योग्य बातें:

यह बदल देता है, कहते हैं, sum((random.randint(1,x) for x in 4 * [6])) साथ 4d6

4 * [6] सूची [6,6,6,6] उत्पन्न करता है।

((random.randint(1,x) for x in [6,6,6,6])) जनरेटर सूची सूची के बराबर है; यह विशेष व्यक्ति 1 और 6 के बीच चार यादृच्छिक संख्याएं लौटाएगा।

2

PyParsing लाइब्रेरी पर एक नज़र डालें। विशेष रूप से, examples पेज एक sample काफी के करीब है कि आप क्या चाहते:

dice2.py

एक पासा रोल पार्सर और जैसे तार के मूल्यांकन के लिए मूल्यांकनकर्ता "4d20 + 5.5 + 4d6.takeHighest (3)" ।

0

मेरी Supybot dice plugin में मैं

r'(?P<sign>[+-])((?P<dice>\d*)d(?P<sides>\d+)|(?P<mod>\d+))' 

साथ अभिव्यक्ति पार्स तो, प्रत्येक पासा और एक कुल संशोधक की कुल संख्या पाने के लिए उन्हें रोल और कुल परिणाम प्राप्त (मैं प्रत्येक पासों का कुल संख्या दिखाना चाहते थे) ।