लिखने के लिए युक्तियाँ


30

एक एक प्रोग्राम है जो आउटपुट का उत्पादन करता है जो प्रोग्राम के सोर्स कोड के समान है। इस वेबसाइट पर, हम आम तौर पर केवल उचित quines के बारे में परवाह करते हैं (लेखन के समय, वर्तमान परिभाषा "आउटपुट का कुछ हिस्सा प्रोग्राम के एक अलग हिस्से द्वारा एन्कोड किया गया है")।

उचित सलाह, या क्वीन जैसी गुणों वाले कार्यक्रम लिखने के लिए आपके पास क्या सलाह है? हमेशा की तरह, प्रत्येक टिप एक अलग उत्तर में होना चाहिए।

tips  quine 

जवाबों:


14

evalकोड को कॉपी करने की आवश्यकता को कम करने के लिए उपयोग करें

बहुमत के लिए कोड की दो प्रतियों की आवश्यकता होती है; एक निष्पादित किया जाना है, एक डेटा के रूप में। यह स्रोत कोड की लंबाई को दोगुना कर सकता है, जिससे स्कोर को बनाए रखना कठिन हो जाता है, और स्कोर को बिगड़ता है यदि आप एक प्रतियोगिता के लिए क्वीन लिख रहे हैं ।

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

यहां यह बताया गया है कि यह कैसे काम करता है (उदाहरण पायथन में लिखा गया है, लेकिन कई अन्य भाषाओं में भी ऐसा ही काम करता है):

d='print("d="+repr(d)+"\\neval(d)")'
eval(d)

2
@QPaysTaxes: मेरा उद्देश्य यहाँ अपने कोड को पठनीय और बनाए रखना है क्योंकि जीत की स्थिति अनुमति देती है। दुर्भाग्य से, यह अभी भी आम तौर पर ASCII लाइन शोर (या सिर्फ नियमित रूप से लाइन शोर अगर मैं जेली का उपयोग कर रहा हूं) से उन लोगों से अप्रभेद्य है जो भाषा के अभ्यस्त नहीं हैं।

14

स्ट्रिंग प्रारूपण का लाभ उठाएं

एक क्वीन बनाने के सबसे आसान तरीकों में से एक स्ट्रिंग को परिभाषित करना है, फिर स्ट्रिंग प्रारूपण के साथ स्ट्रिंग को अपने अंदर रखें।

s='s=%r;print s%%s';print s%s

तो इस उदाहरण में पायथन क्वीन, हम स्ट्रिंग के पहले जो भी है उसके बराबर पहले भाग के साथ एक स्ट्रिंग की घोषणा करते हैं s=, फिर हम स्ट्रिंग को प्रारूपण के साथ सम्मिलित करने की अनुमति देते हैं %r, और अंत में हम स्ट्रिंग को प्रिंट करने और उसे प्रारूपित करने के बाद आते हैं। । अनुगामी newline है क्योंकि printएक अनुगामी newline प्रिंट करता है।

तो टेम्पलेट वास्तव में यह है, पायथन में:

<A>'<A>%r<B>'<B>

मौजूदा कोड को अधिक कोड के साथ विस्तारित करने के लिए:

<more A>s='<more A>s=%r;print s%%s<more B>';print s%s<more B>

9

कड़े कार्य

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

function f(){console.log(f+"f()")}f()

यह कोड एक फ़ंक्शन को परिभाषित करता है और कॉल करता fहै, जिसे कहा जाता है, अपने स्वयं के स्रोत कोड को प्रिंट करता है और उसके बाद कॉल करता है। प्रोग्राम का एकमात्र हिस्सा जिसे डुप्लिकेट करने की आवश्यकता है, वह फ़ंक्शन कॉल है f()। बेशक, फ़ंक्शन बॉडी में कोड का एक मनमाना "पेलोड" शामिल हो सकता है जिसे फ़ंक्शन कहा जाने पर निष्पादित भी किया जाएगा।


एक ही चाल का एक और अधिक कॉम्पैक्ट संस्करण गोल्फिंग भाषाओं में काम करता है GolfScript :

{".~"}.~

और सीजाम :

{"_~"}_~

इनमें से प्रत्येक क्वीन पहले एक अनाम कोड ब्लॉक (ब्रेसिज़ में संलग्न) को परिभाषित करता है, जो कि जावास्क्रिप्ट में एक फ़ंक्शन ऑब्जेक्ट की तरह व्यवहार करता है: इसे निष्पादित किया जा सकता है, और यदि कठोर किया जाता है, तो यह अपना स्रोत कोड लौटाता है। बाकी कोड ( .~गोल्फस्क्रिप्ट में, या _~सीजेएम में) तब ब्लॉक को निष्पादित करता है, जबकि स्टैक पर इसकी एक प्रति छोड़ता है। ब्लॉक के अंदर कोड तब स्टैक पर एक स्ट्रिंग को धकेलता है जो ब्लॉक के बाहर कोड को दोहराता है। जब दुभाषिया बाहर निकलता है, तो यह स्वचालित रूप से स्टैक पर छोड़ी गई सभी चीजों को स्ट्रिंग और प्रिंट करता है। जावास्क्रिप्ट उदाहरण के साथ, इन कोड ब्लॉक को बिना डुप्लिकेट किए अतिरिक्त कोड के एक मनमाने तरीके से ले जाने और निष्पादित करने के लिए भी बनाया जा सकता है।


9

स्ट्रिंग सीमांकक का उपयोग करें जो बचने के बिना घोंसला बनाते हैं

अक्सर, क्वीन लिखने के बारे में सबसे कठिन भागों में से एक भागने वाला कदम है। यह लगभग हर रानी में आवश्यक है; मुद्दा यह है कि आप किसी तरह डेटा स्टोर कर रहे हैं, और आपको उस कोड को दोहराने की आवश्यकता है जो डेटा को क्वीन के आउटपुट में संग्रहीत करता है। उस कोड में डेटा का एक बचा हुआ रूप शामिल होगा, इसलिए प्रोग्राम को एक अनस्कैप्ड रूप दिखाई देगा, और आपको इसे फिर से बचाना होगा।

अनसेफिंग स्टेप को हैंडल करने का सबसे आसान तरीका यह है कि डेटा के भागे हुए और अनसैप्ड रूप स्ट्रिंग स्ट्रिंगर्स की उपस्थिति या अनुपस्थिति में भिन्न होते हैं। इस प्रकार से बचना स्ट्रिंग के चारों ओर एक नई जोड़ी स्ट्रिंग डेलिमिटर को जोड़ने का एक सरल मामला है। दुर्भाग्य से, यह स्पष्ट रूप से केवल तभी काम कर सकता है जब स्ट्रिंग डेलिमिटर खुद को भागने के बिना डेटा में व्यक्त किया जा सकता है।

पर्ल उस भाषा का एक अच्छा उदाहरण है जहाँ यह ट्रिक काम करती है। हालांकि इसकी सामान्य स्ट्रिंग सीमांकक "…"या '…', कम इस्तेमाल किए जाने वाले q(…)घोंसले हैं, जिससे इस तरह की क्वीन को लिखा जा सकता है:

$_=q($_=q(0);s/\d/$_/;print);s/\d/$_/;print

यह एक कोड + डेटा क्वीन है। s///रेगेक्स स्ट्रिंग-रिप्लेसमेंट ऑपरेशन है; हम 0मार्कर के रूप में उपयोग करते हैं, और इसे regex \d("किसी भी अंक") के रूप में मिलान करते हैं, मार्कर का एक से अधिक बार उपयोग करने से बचने के लिए (हालांकि एक और अनुकूलन के रूप में, हम वास्तव में बस 0फिर से उपयोग कर सकते हैं , क्योंकि पर्ल की s///केवल पहली घटना की जगह लेता है चूक)। ध्यान दें कि यहाँ कोई स्पष्ट बचने वाला कदम नहीं है, क्योंकि q(…)सीमांकक को डेटा स्ट्रिंग में शाब्दिक रूप से शामिल किया जा सकता है।


8

कोड + डेटा quines

एक क्वीन के लिए सबसे सामान्य संरचना कुछ इस तरह दिखती है:

डेटा = " पूरे कार्यक्रम का एक बचा हुआ संस्करण,
        इस स्ट्रिंग के साथ एक मार्कर के साथ बदल दिया "
कार्यक्रम = data.replace (
  एक अभिव्यक्ति जो मार्कर का मूल्यांकन करती है लेकिन उसका उल्लेख नहीं करती है ,
  बच गए (डेटा))
प्रिंट कार्यक्रम;

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

इसके लिए कुछ सूक्ष्मताएँ हैं। कुछ भाषाओं में, इस ऑपरेशन को करने का सबसे कठिन हिस्सा बचने वाले कोड को लिखना है; कई भाषाओं में, इसके नाम का उल्लेख किए बिना मार्कर का उत्पादन करना मुश्किल है; और कुछ गूढ़ भाषाओं में, आपको अपने स्वयं के स्ट्रिंग स्ट्रिंग का आविष्कार करना होगा। हालांकि सभी तीन ऑपरेशन बहुत अधिक परेशानी का कारण नहीं हैं।

उदाहरण के लिए, हम एक पायथन क्वीन को स्ट्रिंग से बचने के लिए लिख सकते हैं repr, और 2-चरित्र-अनुक्रम x"स्ट्रिंग का उपयोग करके (जो कि के रूप में प्रतिनिधित्व करने योग्य है "x\"", अर्थात x"स्ट्रिंग के स्ट्रिंग प्रतिनिधित्व में अनुक्रम का उपयोग नहीं करना ): मार्कर के रूप में

d='d=x"\nprint(str.replace(d,"x\\"",repr(d)))'
print(str.replace(d,"x\"",repr(d)))

2
यह ध्यान देने योग्य हो सकता है (संभवतः एक और जवाब में) कि स्ट्रिंग को एक मार्कर की स्थिति में सम्मिलित करना अक्सर एसोलॉन्ग में महंगा होता है, और यह कोड को संरचित करने के लायक हो सकता है जैसे कि स्ट्रिंग स्वयं पहली या अंतिम चीज़ है (शायद इससे अलग हो अंत में एक या दो अक्षर जो आप हार्डकोड कर सकते हैं) ताकि आप जान सकें कि इसे कहां जाना है।
मार्टिन एंडर

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

एक मार्कर का एक विकल्प दो तारों का उपयोग करना है, मैंने ग्लास के लिए ऐसा किया ।
अर्जन जोहान्सन 18

4

स्रोत कोड रैपिंग का शोषण करें

काफी कुछ भाषाओं में (ज्यादातर 2D भाषाएं), स्रोत कोड चारों ओर लपेट सकते हैं; कुछ परिस्थितियों में (जैसे Befunge-98 में, यदि आपका प्रोग्राम एक-लाइनर है) तो कार्यक्रम के अंत में अतीत आपको कार्यक्रम की शुरुआत में ले जाएगा। इस तरह के गैर-व्यवहार व्यवहार का मतलब है कि आप एक ही समय में एक स्ट्रिंग शाब्दिक के अंदर और बाहर कोड लिख सकते हैं; एक बेजोड़ "(या जो कुछ भी स्ट्रिंग सीमांकक है) आपको प्रभावी रूप से पूरे कार्यक्रम के बाकी ( "स्वयं को छोड़कर ) युक्त स्ट्रिंग देगा ।

इस ट्रिक का उपयोग करने में एक समस्या यह है कि आपको स्ट्रिंग मिल जाएगी जैसा कि देखने के दृष्टिकोण से है " प्रोग्राम शुरू होने के बजाय (जैसा आप चाहें) । जैसे, कार्यक्रम को फिर से व्यवस्थित करना सबसे आसान है ताकि "शुरुआत या अंत में दिखाई दे। इसका अर्थ अक्सर आपके कार्यक्रम को कई टुकड़ों में काट देना और जो कुछ भी दिलचस्प / असामान्य प्रवाह नियंत्रण आपकी भाषा में होता है उसका उपयोग करना (अधिकांश भाषाएं जो कार्यक्रम के चारों ओर स्ट्रिंग शाब्दिकता को लपेटने देती हैं, उनमें से एक अच्छा चयन है)।

एक अच्छा उदाहरण है @ जस्टिन बीफंज -98 क्वीन :

<@,+1!',k9"

"कार्यक्रम के अंत में बेजोड़ पूरे कार्यक्रम को एक स्ट्रिंग शाब्दिक में लपेटता है, इसलिए ( <शुरुआत में बाएं से दाएं चल रहा है ) हम सभी को प्रोग्राम को आउटपुट करना होगा ( 9k), फिर आउटपुट डबल कोट्स ( '!1+,)। बाहर निकलें ( @)। इससे प्रोग्राम की दो प्रतियां (एक कोड के रूप में, एक डेटा के रूप में) की आवश्यकता होती है; दो प्रतियां कोड का एक ही टुकड़ा हैं, बस अलग-अलग तरीकों से व्याख्या की गई है।


4

एक संरचना की याद रखें

मुझे 2 के बजाय तीन भागों के रूप में क्वाइन्स के बारे में सोचना पसंद है :

  • भाग 1: भाग 2 और 3 का डेटा प्रतिनिधित्व उत्पन्न करें।
  • भाग 2: डेटा का उपयोग एल्गोरिदम को बैक पार्ट 1 प्रिंट करने के लिए करें।
  • भाग 3: भाग 2 और 3 को प्रिंट करने के लिए प्रतिनिधित्व को डिकोड करें।

इससे क्वीन के बारे में सोचना आसान हो सकता है। यहां एक पायथन क्वीन है, जिसमें प्रत्येक लाइन एक भाग के समान है:

s = "print(\"s = \" + repr(s))\nprint(s)"
print("s = " + repr(s))
print(s)

कभी-कभी, आप evalदोहराव को हटाने के लिए या इसके समान का उपयोग करते हैं , लेकिन आम तौर पर मैंने पाया है कि यह सरल उद्धरण लिखने में मदद करता है।

आइए एक नजर डालते हैं दो अलग-अलग अंडरलोड क्वाइन पर। यह पहला है:

(:aSS):aSS

पहला भाग है (:aSS), जो डेटा प्रतिनिधित्व उत्पन्न करता है। दूसरा है :aS, जो प्रिंट करता है(:aSS) । तीसरा भाग है S, जो प्रिंट करता है :aSS

यहाँ दूसरी रानी है:

(:aS(:^)S):^

सबसे पहले, यह फिट नहीं लगता है। लेकिन अगर आप क्वीन का विस्तार करते हैं, तो आपको मिलेगा:

(:aS(:^)S):aS(:^)S

अब (:aS(:^)S)भाग 1 है, :aSभाग 2 है, और (:^)Sभाग 3 है।

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