एक गोल्फ भाषा में भंडारण के लिए युक्तियाँ


16

मैं एक गोल्फ भाषा लिख ​​रहा हूं।

क्या आप एक कोड-गोल्फ भाषा में भंडारण के लिए चर, स्टैक (ओं), टेप, रजिस्टर आदि का सुझाव देते हैं? निहित इनपुट के बारे में क्या?

किसी न किसी परिभाषा:

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

मैं अलग-अलग परिदृश्यों के लिए प्रत्येक विकल्प के फायदे और नुकसान, और समग्र रूप से जानना चाहूंगा। कृपया राय, और तर्क के साथ बैकअप स्टेटमेंट से बचें।


1
मुझे लगता है कि आपको अपने प्रश्न में इन शर्तों की एक परिभाषा शामिल करनी चाहिए
क्रिति लिथोस

2
@ तकनीकी रूप से भंडारण विधि इस बात पर निर्भर नहीं है कि आप किस तरह की गोल्फिंग भाषा बना रहे हैं, जिस तरह की गोल्फिंग भाषा भंडारण पद्धति पर निर्भर है ...
ETHproductions

1
@ETHproductions वे पूरी तरह से अन्योन्याश्रित हैं।
18

1
अगर आप उन्हें पसंद नहीं करते हैं, तो मैंने विभिन्न स्टोरेज टर्म्स की कुछ गलत परिभाषाएँ जोड़ दी हैं।
ETHproductions

2
भंडारण विधि और भाषा के प्रकार के बीच बहुत करीबी संबंध है, लेकिन मुझे लगता है कि आपको दोनों को देखना होगा। उदाहरण के लिए, "अनिवार्य" भाषाएं (जो लोग अपने निर्देशों को सख्ती से बाएं से दाएं करते हैं) स्टैक-आधारित (CJam, 05AB1E), टेप-आधारित (BrainF ***), या कुछ और पूरी तरह से हो सकते हैं (वी, जो उपयोग करता है) एक बड़ा 2 डी स्ट्रिंग "बफर" कहा जाता है, कुछ रजिस्टरों के साथ)। वहाँ भी उपसर्ग-आधारित भाषाएँ (पायथ), infix- आधारित भाषाएँ (Japt, Pip, और मूल रूप से प्रत्येक मुख्यधारा लैंग), लिंक-आधारित भाषाएँ (Jelly), आदि हैं, जिनमें से सभी का उल्लेख विधियों में से शायद ही कोई हो।
ETHproductions

जवाबों:


4

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

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

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

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

लेकिन ध्यान दें, आप एक बाइनरी ट्री के आकार को प्रति ऑपरेटर केवल 2 बिट्स में एन्कोड कर सकते हैं। इसलिए, यदि आपकी भाषा में 64 से कम ऑपरेटर हैं, तो आप वास्तव में पारंपरिक मॉडलों को अनदेखा कर सकते हैं और बस पूरे पेड़ को स्पेयर बिट्स में कॉल कर सकते हैं (उन्हें Comb_parent और bottom_leaf झंडे कहते हैं)। यहां तक ​​कि अगर अधिक ऑपरेटर हैं, तो आप इसे बदलने के लिए एक अच्छा डिफ़ॉल्ट (जैसे जेली का मॉडल) और 3 संशोधक बना सकते हैं।

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

संदर्भ के लिए, एक बाइनरी ट्री के सही एन्कोडिंग का आकार कैटलन संख्याओं का लघुगणक है । और एक "बाइनरी" डैग के सही एन्कोडिंग का आकार A082161 का लघुगणक है , लेकिन स्पष्ट रूप से अव्यावहारिक है। यह अलग तर्क के साथ एक ऑपरेटर मानता है दो अलग-अलग ऑपरेटरों को आदेश देता है, जब यह नहीं होता है तो एक और बिट जोड़ता है।

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


7

मैं उन सभी को सुझाव देता हूं!

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

एक उदाहरण:

  • कहें कि मैं इनपुट के रूप में दो नंबर लेना चाहता हूं, और उनकी स्ट्रिंग लंबाई जोड़ना चाहता हूं
  • चर इसके लिए बेहतर हो सकते हैं (स्टैक नहीं हो सकता है)
  • GolfScript में उदाहरण कोड (अंतर्निहित इनपुट के साथ):

    ~,\,+
    ~ # Eval input (e.g. "1 2" > 1, 2)
    , # Take Length
    \ # Reverse items on the stack
    , # Take Length
    + # Add
      # Implicit output
    

    हालांकि, चर के साथ (मुझे पता है कि यह लंबा है, बस स्टैक पर स्थानों को स्वैप करने की आवश्यकता नहीं है):

    ~,:a;,:b;ab+
    ~ # Eval input
    , # Get length
    :a# Store in "a"
    ; # Discard value left on stack
    , # Length
    :b# Store in "b"
    ; # Discard
    a # Recall a
    b # Recall b
    + # Add
      # Implicit output
    

भार के

एक और चीज जो मददगार हो सकती है वह है ओवरलोड्स। उदाहरण के लिए, यदि आपके पास एक वैरिएबल स्टोरिंग फंक्शन है, तो शायद इसे मोनड (वन-इनपुट फंक्शन) के रूप में इस्तेमाल किया जा सकता है। मुझे स्टैक या टेप में जोड़ने के लिए J / K / APL के टर्म आउट साइड का यकीन नहीं है।

उदाहरण:

c12 # Stores "1" into register 2
c1] # Pushes "1" onto the stack ("]" is used to denote the end of the monad)

हो सकता है कि यदि किसी तर्क को गलत प्रकारों के साथ कहा जाता है, तो यह एक कतार में जुड़ जाता है जो तब तब होता है जब स्टैक खाली होता है?
फल खाने

5

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

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

केवल उन्हीं के कार्यों को सीमित न करें जो उनके नाम या परिभाषाएं गर्त का सुझाव देती हैं - जैसे कुछ कार्य put the 1st thing of the stack on top of the stackनिश्चित रूप से मदद कर सकते हैं।


5

मूल रूप से दो प्रकार के भंडारण होते हैं जिन्हें अलग तरीके से संभालने की आवश्यकता होती है; हाल ही में उत्पन्न मूल्यों और / या आदानों तक पहुंच; और दीर्घकालिक भंडारण।

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

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

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


0

मैं एक टेप और एक रजिस्टर का सुझाव देता हूं।

मैं ढेर पर टेप पसंद करता हूं क्योंकि टेप में कम तत्व होते हैं, जिससे उनमें हेरफेर करना आसान हो जाता है। इसके अलावा, रजिस्टर में टेप में तत्वों को रखने में सक्षम होना और इसके विपरीत, आसान, छोटे कोड के लिए बनाता है।

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