प्रोलॉग में गोल्फिंग के लिए टिप्स


16

Prolog में गोल्फिंग के लिए आपके पास क्या सामान्य सुझाव हैं? मैं ऐसे विचारों की तलाश कर रहा हूं जो सामान्य रूप से कोड गोल्फ समस्याओं के लिए लागू हो सकते हैं जो कम से कम कुछ हद तक प्रोलॉग के लिए विशिष्ट हैं (जैसे कि एक अक्षर चर प्रोग्राम के आकार को कम करने के लिए प्रोलॉग के लिए विशिष्ट नहीं है)।

कृपया अपने सुझावों में बताएं कि क्या यह प्रोलोग के कार्यान्वयन के लिए विशिष्ट है (जैसे SWI- प्रोलॉग विशिष्ट बिल्ट-इन)

कृपया प्रति उत्तर केवल एक टिप, या सुझावों की एक सूची पोस्ट करें जो सभी एक ही मुख्य विचार से निकटता से संबंधित हैं।


1
prologटैग थोड़े बेकार है। जब तक हमारे पास एक व्याख्या प्रस्ताव चुनौती नहीं है, हमें इसकी आवश्यकता नहीं है।
बिल्ली

जवाबों:


11

नामों के लिए प्रचालकों का उपयोग करें

जब तक ऑपरेटर पूर्वनिर्धारित ऑपरेटरों ( यहां सूचीबद्ध ) में से एक है, तब तक नाम के रूप में विधेय परिचालकों को देना संभव है और पहले से ही एक विधेय के रूप में परिभाषित नहीं किया गया है। यह कुछ बाइट्स को तब बचाता है जब ऑपरेटर को परिभाषित करने और कॉल करने के बाद कॉल करता है क्योंकि ऑपरेटर की भविष्यवाणी सामान्य name(arg1,arg2,etc..)रूप में लिखे जाने की आवश्यकता नहीं है और इसे ऑपरेटर के साथ अपेक्षा के अनुसार कहा जा सकता है।

एक और दो तर्क की भविष्यवाणी के लिए, वे क्रमशः यूनरी और बाइनरी ऑपरेटरों के नाम दे सकते हैं। उच्च एरियर की भविष्यवाणी के लिए, हम अभी भी पैटर्न मिलान के उपयोग से कोष्ठकों से बच सकते हैं। उदाहरण के लिए यदि हमारे पास एक विधेय है A+B+C:-..., तो प्रोलॉग अपने ऑपरेटर की पूर्ववर्तीता और सहानुभूति नियमों का उपयोग करके इसे बदल देगा, (A+B)+C:-...जिसमें एक ऑपरेटर विधेय है जहां पहला तर्क पैटर्न से मेल खाता है A+B। या A-B+C*D:-...जो (A-B)+(C*D)इसका पहला तर्क बन जाता है वह है पैटर्न से मेल खाता हुआ A-Bऔर इसका दूसरा है पैटर्न से मिलान C*D

उदाहरण

_+_+_.
A-B+C*D:-between(A,B,C),C+D.
\X:-X>1,X<10.
X+Y:-length(Y,X),member(X,Y).



5+[10,5,3,2,5],a+b+c,0-20+X*[2,4,6,5,40],\9.

आउटपुट होगा X = 5.

इसे ऑनलाइन आज़माएं!

परिणाम

चूंकि DCGs विधेय के लिए वाक्य रचना चीनी हैं, इसलिए उन्हें भी नामों के लिए ऑपरेटर दिए जा सकते हैं। यह उम्मीद के अनुसार काम करता है जब उन्हें डीसीजी से डीसीजी के रूप में कॉल किया जाता phraseहै या डीसीडी के साथ काम करने के लिए डिज़ाइन किए गए विधेय या अन्य का उपयोग किया जाता है। जब उन्हें विधेय के रूप में बुलाया जाता है तो कोष्ठक की आवश्यकता होती है (उदाहरण के लिए जैसे A+B-->...बुलाया जाना चाहिए +(A,B,...)) क्योंकि DCG विधेयकों में उनके अंतर सूचियों के लिए अतिरिक्त दो तर्क होते हैं। ऑपरेटर पैटर्न मिलान का उपयोग करके दो से अधिक तर्कों के साथ DCGs नाम के ऑपरेटर के लिए, तब यह सुनिश्चित करना महत्वपूर्ण है कि इसे एक विधेय के रूप में कहा जाता है कि पैटर्न मिलान किए गए ऑपरेटरों को सही तरीके से वितरित किया जाता है।

DCG को ऑपरेटर नाम देना जो बिना किसी अतिरिक्त तर्क के उपयोगी हो सकता है यदि आपको उन्हें अपने कार्यक्रम के भीतर कॉल करने की आवश्यकता है, तो आप कोष्ठक का उपयोग किए बिना ऐसा कर सकते हैं। सावधानी बरतने की आवश्यकता है क्योंकि यह मामला हो सकता है कि आप कोष्ठक में जो बचाते हैं वह आप सटे हुए परिचालकों को पार्स करने के लिए आवश्यक स्पेसिंग में खो सकते हैं।

उदाहरण

/ -->a+b+X,X+d+e.
A+B+C-->[A],[B],[C].


X/[],member(c,X),phrase(f+o+o,Y),+(b+a,r,Z,[]).

आउटपुट होगा

X = [a, b, c, c, d, e],
Y = [f, o, o],
Z = [b, a, r].

इसे ऑनलाइन आज़माएं!

चेतावनियां

एकरी संचालकों के साथ +और -, प्रोलोग एक या विधेय के लिए कॉल के बजाय संख्याओं की व्याख्या +20या के -20रूप में करेगा । दी गई एकात्मकता के रूप में या नामों को अभी भी कोष्ठक ( , ) का उपयोग करके संख्या पर बुलाया जा सकता है । यदि कोष्ठकों से अतिरिक्त बाइट्स से परहेज जैसे वांछनीय अन्य एकल ऑपरेटरों है , , आदि नामों के रूप में उपयोग किया जा सकता।+/1-/1+-+(20)-(20)\$

विधेयकों के नाम से पैटर्न मिलान और ऑपरेटर का संयोजन पूरी तरह से दोषों के बिना नहीं है। यदि आपके पास दो विधेय हैं जिनके ऑपरेटर के नाम के समान है और पैटर्न मिलान के साथ एक दूसरे के मुकाबले कड़ाई से अधिक सामान्य है, तो अधिक सामान्य एक को पहले कहा जा सकता है या यदि कम सामान्य एक विफल रहता है (स्रोत में उनके आदेश के आधार पर) । उदाहरण के लिए ऊपर दिए गए उदाहरण में यदि A-B+C*Dइसके इनपुट से मेल नहीं खाता है तो प्रोलॉग कॉलिंग की कोशिश करेगा X+Y। यह एक त्रुटि के परिणामस्वरूप होगा क्योंकि पूर्णांक होना length/2आवश्यक Yहै जो कि यह नहीं होगा क्योंकि यह फॉर्म में होगा C*D। यह सुनिश्चित करने से बचा जा सकता है कि किसी भी दो विधेयकों के पास उनके नाम के समान ऑपरेटर नहीं है या यदि वह विफल रहता है तो कटौती और स्रोत के सावधानीपूर्वक आदेश का उपयोग कर रहा है।


3
यह आश्चर्यजनक है कि कोड गोल्फ के लिए यह चाल कितनी उपयोगी है। मैंने केवल इस टिप का उपयोग करके एक उत्तर की बाइट-गिनती को 16% कम कर दिया है!
DLosc

7

हर संभव मामले को एक नियम में रखने की कोशिश करें

प्रोलॉग में प्रोग्राम करने का स्वच्छ तरीका एक ही विधेय के लिए कई नियमों की घोषणा करना है। उदाहरण के लिए, एक संचायक के साथ सूची को उलटने के लिए एक विधेय इस तरह दिखेगा:

r([],Z,Z).
r([H|T],Z,R):-r(T,[H|Z],R).

कोड-गोल्फ में, हम पहले नियम को हटा सकते हैं, और ;दूसरे नियम के अंत में पुनरावर्तन कोड को जोड़ सकते हैं :

r([H|T],Z,R):-r(T,[H|Z],R);R=[H|Z].

हम जानते हैं कि r(T,[H|Z],R)यदि टी खाली है, तो पहली स्थिति विफल हो जाएगी, अर्थात यदि पुनरावृत्ति को समाप्त करने की आवश्यकता है और इस प्रकार हम अपनी समाप्ति को इसके बाद या खंड के रूप में जोड़ सकते हैं।

एक ही सिद्धांत बहुत सारी स्थितियों में काम करता है। ध्यान दें कि कभी-कभी ऐसा करने के बजाय किसी अन्य नियम की घोषणा करना वास्तव में कम होता है।


7

टुपल कंस्ट्रक्टर और कंस जोड़े के रूप में अंकगणितीय ऑपरेटरों का उपयोग करें

यदि आपको दो या दो से अधिक मूल्यों वाले एकल संरचना को पास करने की आवश्यकता है, तो उपयोग करने के लिए सबसे स्पष्ट चीज एक सूची है, उदाहरण के लिए [A,B]। यह वास्तव में क्रिया है, हालांकि।

एक विकल्प है। प्रोलॉग मान बहुत अधिक मनमाने ढंग से नेस्टेड संरचना को संग्रहीत कर सकते हैं, जिसका मूल्यांकन नहीं किया जाता है। यहाँ एक उदाहरण दिखाया गया है कि यह कैसे काम करता है:

| ?- member(member(A,B),C).
C = [member(A,B)|_] ? ;
C = [_,member(A,B)|_] ? ;
(etc.)

member(A,B)इस स्थिति में सिर्फ एक नामांकित टपल है, और बाहर member(जो एक फ़ंक्शन कॉल है) इसे इस तरह से मान रहा है।

हालांकि नामांकित ट्यूल गैर-गोल्फ प्रोलॉग प्रोग्रामिंग में काफी उपयोगी हैं, वे सूची दृष्टिकोण की तुलना में अधिक क्रियाशील लग सकते हैं। हालाँकि, हम टुप्ल कंस्ट्रक्टर के नाम पर बहुत अधिक मनमाने पात्रों का उपयोग कर सकते हैं (यह मानते हुए कि वे ठीक से उद्धृत हैं); कुछ प्यारा memberया एक जैसे चरित्र के बजाय a, हम ऐसा कुछ कर सकते हैं:

| ?- A = '-'('/'(1,2), '/'(3,4)).
A = 1/2-3/4

यहाँ, हमारे टपल निर्माता हैं '-'और '/'। और यह नोट करना दिलचस्प है कि सुंदर-प्रिंटर ने उनके साथ क्या किया; यह tuples के लिए infix संकेतन का उपयोग कर रहा है । यह वास्तव में बहुत कठिन है, और एक ही तरीका है कि तुलनीय अंकगणितीय ऑपरेशन होगा। (यह भी बताता है कि अंकगणित का उपयोग क्यों isनहीं किया जाता है =; टपल के साथ A = 1+2एकीकृत होगा , इसलिए अलग-अलग वाक्यविन्यास को वास्तव में बिना अंकगणित अंकगणितीय अभिव्यक्ति का मूल्यांकन करने की आवश्यकता होती है।) क्योंकि एक ट्यूलल कंस्ट्रक्टर को कुछ कहा जाना है , आप एक ऐसे चरित्र का उपयोग कर सकते हैं जिसमें एक शब्द है। सिंटैक्स (और बोनस के रूप में, औरA '+'(1,2)-/गैर-गोल्फ कोड में कुछ सबसे आम विकल्प भी हैं, जब वे कुछ सार्थक के बजाय एक त्वरित फेंकने वाला टपल निर्माण चाहते हैं, उसी तरह से जो iअक्सर लूप चर के रूप में उपयोग किया जाता है, इसलिए वे आपके उपयोग में पूरी तरह से उचित हैं इनपुट और आउटपुट यदि आप किसी कारणवश वहां ट्यूपल चाहते हैं)।

'-'और '/'ट्यूलल कंस्ट्रक्टर के लिए अच्छे विकल्प हैं क्योंकि उनके पास अच्छी तरह से व्यवहार और उपयोगी पूर्वता है, जिससे आप ट्यूलल लिटरल को ट्रेसली लिख सकते हैं। हालाँकि, ध्यान दें कि कार्यक्रम के अंदर मध्यवर्ती मान उत्पन्न होने पर आपको पूर्वता के बारे में चिंता करने की आवश्यकता नहीं है। प्रोलॉग टुपल्स को स्रोत कोड के बजाय एक पेड़ के रूप में संग्रहीत करता है, और सुंदर-प्रिंटर इसे अस्पष्ट रूप से आउटपुट कर सकते हैं:

| ?- A = '-'('-'(1,2), '-'(3,4)).
A = 1-2-(3-4)

क्योंकि टुपल सिंटैक्स इतना f(A,B)अधिक है ( f(A-B)आप की तुलना में छोटा नहीं है ), आप बिना किसी लागत के कई प्रेडिक्टेट तर्कों को प्रतिस्थापित कर सकते हैं, जिसका अर्थ है कि यदि किसी विधेय को किसी अन्य डेडिकेटेट को इसके दो या अधिक दलीलों को पारित करने की आवश्यकता है, तो आप उन्हें अक्सर बना सकते हैं। एक टुपल और बस टपल को पास करें (हालांकि इसके लिए विधेय के अलावा सभी कॉलों को बदलने की आवश्यकता होगी, टपल कंस्ट्रक्टरों और कॉमाओं के उचित मिश्रण का उपयोग करने के लिए।

इस सिंटैक्स का एक और फायदा यह है कि यदि आपको सूचियों का आंतरिक रूप से उपयोग करने की आवश्यकता है (बजाय मानक विधेय के साथ हस्तक्षेप करने के लिए); एक सूची मूल रूप से नेस्टेड कॉन्स कोशिकाओं का एक सेट है, और एक कॉन्स सेल कंस्ट्रक्टर के साथ सिर्फ एक टपल है '.', जैसा कि देखा जा सकता है:

| ?- Q = '.'('.'(A,B),'.'(C,D)).
Q = [[A|B],C|D]

यदि आपका कोड "मैन्युअल रूप से" सूचियों का उपयोग करता है, तो इसकी तुलना में बहुत कम टफ कंस्ट्रक्टर का उपयोग करने के लिए बहुत कुछ समझ में आता है '.'। मेरे लिए एक सामान्य विकल्प है कि आप एक आम सेल का प्रतिनिधित्व करें '/'(Tail,Head)(क्योंकि यह सबसे पठनीय है, जो आप वर्णों को बर्बाद किए बिना डिबग आउटपुट में प्राप्त कर सकते हैं)। ध्यान दें कि आप शायद अपने स्वयं के []समकक्ष भी चाहते हैं; आप उपयोग कर सकते हैं, []लेकिन यह दो बाइट्स लंबा है, और एक-एक बाइट परमाणु (सभी निचले अक्षर) हैं जो आप इसके बजाय उपयोग कर सकते हैं।

उदाहरण के लिए, निम्न सूची:

[1,2,3]

इस तरह से एक ही संख्या में वर्णों को मैन्युअल प्रतिनिधित्व में बदला जा सकता है:

x/3/2/1

फ़ायदा उठाते हुए कि [H|T]-स्टाइल पैटर्न मैच के रूप में अब और अधिक स्पष्ट रूप से लिखा जा सकता है T/H, और खाली सूची के खिलाफ एक परीक्षण के xबजाय केवल लंबे समय तक []। (बेशक, यह स्पष्ट नुकसान यह है कि के साथ आता है member, appendआदि, इस प्रतिनिधित्व पर काम नहीं करेगा।)


+1! उपयोग करते समय -और एकल उद्धरणों की कोई आवश्यकता नहीं है /। ये पहले से ही बिल्कुल सामान्य परमाणु हैं।
चटाई

और, चारों ओर एकल उद्धरणों की कोई आवश्यकता नहीं है ., बशर्ते कि निम्नलिखित अक्षर न तो %एक लेआउट हों।
झूठी

6

एक चाल जो अक्सर उपयोगी होती है: पूर्णांक अंकगणित के लिए सीएलपी (एफडी) बाधाओं का उपयोग करें विधेय प्राप्त करने के लिए जो स्वचालित रूप से कई दिशाओं में उपयोग किया जा सकता है, इस प्रकार शर्तों और समर्पित शाखाओं और वेरिएंट से बचा जा सकता है।

बी-प्रोलॉग या जीएनयू प्रोलॉग का उपयोग करें, जहां ऐसी अड़चनें किसी भी पुस्तकालय को लोड करने की आवश्यकता के बिना, बॉक्स से बाहर उपलब्ध हैं।


2
यह हमेशा कुछ ऐसा है जिसे मैं SWI-Prolog से नफरत करता हूं जब यहां चुनौतियां हैं। सीएलपीएफडी का उपयोग करने से कुछ चीजें बहुत अधिक साफ और कम हो जाती हैं, लेकिन आपको इसे काम करने के लिए बहुत सारे अतिरिक्त कोड जोड़ने होंगे (स्वयं द्वारा शामिल करना बहुत ...) जो आमतौर पर इसके लायक नहीं बनाता है। मुझे लगता है कि मैंने केवल इस उत्तर में इसका उपयोग किया है ।
घातक

3
मैं उससे भी नफरत करता हूं, और यह सुनिश्चित करने के लिए कि आखिरकार वह समय आएगा जब प्रीलोडेड केlibrary(clpfd) रूप में या कम से कम ऑटोलोडेड लाइब्रेरी के रूप में एसडब्ल्यूआई-प्रोलॉग में भी उपलब्ध होगा । घोषणात्मक अंकगणित को सभी उपयोगकर्ताओं द्वारा पूरी तरह से समझा और सराहा जाने तक कुछ साल लग सकते हैं, जिनके पास पुरानी, ​​निम्न-स्तरीय विशेषताओं के साथ अब दशकों का अनुभव है। जितना आप सीएलपी (एफडी) का उपयोग और वकालत करते हैं, उतनी ही जल्दी हम इसे डिफ़ॉल्ट रूप से प्राप्त करेंगे। तब तक, आप बस अपने और बस राज्य में डाल सकते हैं कि आप SWI- प्रोलॉग के "संस्करण" का उपयोग कर रहे हैं। :- use_module(library(clpfd)).~/.swiplrc
मैट

5

सूचियों की सूची के लिए छोटे सिंटैक्स और नक्शे घोषित करने का एक तरीका

आप सूचियों की सूची पर बाइट्स बचा सकते हैं। यदि आपके पास एक सूची है [[1,2],[3,4]], तो आप वास्तव में इसे घोषित कर सकते हैं [1:2,3:4], जो 4 कोष्ठक = 4 बाइट्स बचाता है। ध्यान दें कि आप :(उदाहरण के लिए ^) की तुलना में कुछ और उपयोग कर सकते हैं ।

1:2वास्तव में उस मामले में एक सूची नहीं है (जबकि [1,2]थी), इसे आंतरिक रूप में दर्शाया गया है :(1,2)। इसलिए आप उन उपनलों पर सूचियों पर काम करने वाले विधेय का उपयोग नहीं कर सकते हैं जो कॉलन का उपयोग करते हैं।

इस ट्रिक का इस्तेमाल मुख्य रूप से मानचित्रों को घोषित करने के लिए किया जाता है, अर्थात उनके साथ जुड़ी मूल्यों की सूची। उदाहरण के लिए, यदि आप एक ऐसा नक्शा घोषित करना चाहते हैं Mजिसमें अंग्रेजी और फ्रेंच दोनों में अंकों की वर्तनी हो, तो आप कुछ ऐसा कर सकते हैं:

M=[0:'Zero':'Zéro',1:'One':'Un',2:'Two':'Deux', ... ]

फिर आप उदाहरण के लिए जैसे अंतर्निहित विधेयकों के साथ मानचित्र के तत्वों को पुनः प्राप्त कर सकते हैं member/2। उदाहरण के लिए, यदि आप अंक और अंग्रेजी शब्द के अनुरूप चाहते 'Quatre'हैं M, तो आप कर सकते हैं:

member(Digit:Name:'Quatre',M).

1
आप इसे सामान्य कर सकते हैं। उदाहरण के लिए, आप के [[1,2],[3,4]]रूप में wirte कर सकते हैं 1*2+3*4, जो है +(*(1,2),*(3,4))और इस प्रकार केवल एक बाइट का उपयोग करें जहां आपको अन्यथा कोष्ठक खोलने और बंद करने के लिए दो की आवश्यकता होगी।
मैट

: दोहरे उद्धरण सूचियों भी कम कर रहे हैं "abc"की जगह में[a,b,c]
झूठी

5

एक साफ-सुथरी चाल: जब आपको असफल होने की आवश्यकता हो , तो ऐसी चीज़ का उपयोग करें जो झूठी / 0 के बराबर हो  , लेकिन छोटी हो, जैसे:

? - बार-बार, लेखनी (हाय), ० = १

3
ओब्लिगेटरी द आर्ट ऑफ़ प्रोलॉग उद्धरण: " प्रोलॉग प्रोग्रामिंग में (इसके विपरीत, शायद, सामान्य रूप से जीवन के लिए) हमारा लक्ष्य जितनी जल्दी हो सके असफल होना है "। मज़ेदार तथ्य: आप भी उपयोग कर सकते हैं \+!के रूप में एक 3 विफल करता है जो वास्तव में कटौती से चलाता नहीं अजीब तरह से बाइट्स !(देखें इस के लिए कारण है कि )। मुझे नहीं लगता कि 3 बाइट्स से कम में असफल होना संभव है।
घातक

मैं उस समय के बारे में भी सोच रहा था जब मैंने यह लिखा था ;-)
चटाई

2
हमें वास्तव में दोनों संस्करणों की आवश्यकता है, \+!बाईं ओर अन्य ग्राफिक पात्रों के 0=1लिए glues , जबकि नामों के लिए बाईं ओर glues।
झूठी

5

अलग-अलग कॉलिंग मोड के साथ एक विधेय का पुन: उपयोग करें

उदाहरण के लिए, आप एक संरचना को एक ही विधेय के साथ पार्स और प्रिंट कर सकते हैं, एक बार एक चर तर्क के साथ और दूसरी बार एक ग्राउंड टर्म के साथ। मैं में इस दृष्टिकोण का इस्तेमाल किया मेक Stretchy सांप चुंबन । सभी चुनौतियों में, यह संभव नहीं है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.