Brainfuck में गोल्फ के लिए युक्तियाँ


23

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

जवाबों:


25

प्रति उत्तर एक टिप लगाने से बहुत अधिक उत्तर मिलेंगे।

  • Brainfuck में सोचना सीखें। यह किसी भी चीज़ से बहुत अलग है। पढ़ें और लिखें, और फिर से लिखें, और बहुत सारे ब्रेनफैक कार्यक्रमों को फिर से लिखें। भाषा आपको काम करने के लिए बहुत कुछ नहीं देती है, इसलिए इसका उपयोग करना महत्वपूर्ण है जो आपको लचीले और कुशलता से देता है। अपने और भाषा के बीच किसी भी सार को प्राप्त न होने दें - वहाँ पहुँचें और उसके साथ हाथापाई करें।

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

  • वह और तथ्य यह है कि हर >या< लागत का मतलब है कि मेमोरी लेआउट का विवरण महत्वपूर्ण है। अपने लेआउट के कई रूपों को आज़माएं क्योंकि आपके पास धैर्य है। और याद रखें, आपके मेमोरी लेआउट को स्थानों पर डेटा की कठोर मैपिंग करने की आवश्यकता नहीं है। यह निष्पादन के पाठ्यक्रम को जोड़ सकता है।

  • बड़े पैमाने पर, विभिन्न एल्गोरिदम को लागू करने पर विचार करें और यहां तक ​​कि प्रयास करें। प्रारंभ में यह बिल्कुल स्पष्ट नहीं होगा कि एल्गोरिथ्म सबसे अच्छा क्या होगा; यह भी स्पष्ट नहीं हो सकता है कि बुनियादी दृष्टिकोण क्या सबसे अच्छा होगा, और यह संभवतः एक सामान्य भाषा में सबसे अच्छा होगा की तुलना में कुछ अलग होगा।

  • यदि आप बड़े या चर-आकार के डेटा के साथ काम कर रहे हैं, तो देखें कि क्या कोई तरीका है जिससे आप संभवतः इसके साथ स्थानीय रूप से निपट सकते हैं, बिना यह ध्यान रखे कि यह कितना बड़ा है या आपके संख्यात्मक स्थान के भीतर है।

  • एक ही डेटा दो अलग-अलग चीजें हो सकती हैं। (सबसे अधिक बार, एक संख्या या चरित्र और एक गैर- अक्षीय स्थिति मार्कर भी। लेकिन यादृच्छिक देखें। बी , जहां एक सेलुलर ऑटोमेटन के एक सेल के मूल्य के रूप में एक बिट काउंटर दोगुना हो जाता है।)

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

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

  • सौभाग्य! बहुत कम लोग ब्रेनफक को संक्षिप्त रूप से लिखने के लिए परेशान करते हैं, लेकिन मुझे लगता है कि यह एकमात्र तरीका है कि भाषा संभवतः निरंतर ध्यान देने का औचित्य साबित कर सकती है - एक आश्चर्यजनक रूप से अस्पष्ट कला के रूप में।


3
इस पढ़ना मुझे अब Brainfuck में प्रोग्रामिंग की कोशिश करना चाहते है ..
Claudiu

पवित्र बकवास, सोचा कि मैंने आपका नाम पहचाना। आपके ब्रेनफक कार्यक्रमों के बड़े प्रशंसक, विशेष रूप से आपके सुपर-शॉर्ट आत्म-दुभाषिया!
जो किंग

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

"अपने लेआउट के कई रूपों को आज़माएं, जैसा कि आपके लिए धैर्य है," या ब्रूट-फ़ोर्स कर सकते हैं : P
Esolanging Fruit

9

यहाँ कुछ सुझाव:

स्थिरांक:

Esolangs 'स्थिरांक पेज विशिष्ट मान बनाने के लिए कम से कम तरीकों में से एक अत्यंत उपयोगी सूची है। मैं अपने आप को इस कार्यक्रम में प्रति कार्यक्रम कम से कम दो बार परामर्श देता हूं।

सब कुछ की शुरुआत:

+++[[<+>>++<-]>]

यह टेप को प्रारूप 3 * n ^ 2 में सेट करता है, जो दिखता है

3 6 12 24 48 96 192 128 0 0 '

यह क्यों इतना महत्वपूर्ण है?

चलो सूची में नीचे जाते हैं:

  • 3 और 6 बोरिंग हैं
  • 12: करीब 10 (न्यूलाइन) या 13 (गाड़ी वापसी)। 0-9 के लिए काउंटर के लिए भी इस्तेमाल किया जा सकता है
  • 24: 26 के करीब, वर्णमाला में अक्षरों की संख्या
  • 48: ASCII के लिए 0
  • 96: 97 के करीब, ASCII के लिए a
  • 196 और 128: 196-128 = 64, 65 के करीब, ASCII के लिए A

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

एक व्यावहारिक उदाहरण:

सभी अपरकेस और लोअरकेस अक्षरों और अंकों को प्रिंट करना।

एल्गोरिथ्म के साथ:

+++[[<+>>++<-]>]<<[-<->]<<<<++[->>+.>+.<<<]<--[>>.+<<-]

के बिना:

+++++++++++++[->+++++++>++>+++++>++++>+<<<<<]>+++++>[-<+.>>.+<]>>---->---[-<.+>]

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

एक ही नस में अन्य दिलचस्प एल्गोरिदम की एक जोड़ी:

3 * 2 ^ n + 1:

+++[[<+>>++<-]+>]
Tape: 4 7 13 25 49 65 197 129 1 0'

यह मानों को 1 से दूर करता है, जो कुछ चीजों को पूरा करता है। यह 12 कैरिज रिटर्न, 64 अपरकेस वर्णमाला की वास्तविक शुरुआत और 24 को 26 के करीब बनाता है।

2 ^ n:

+[[<+>>++<-]>]
Tape: 1 2 4 8 16 32 64 128

क्योंकि 64 अपरकेस अक्षरों के लिए अच्छा है, 32 अंतरिक्ष के लिए ASCII है, और 128 का उपयोग 26 (130/5 = 26) के लिए काउंटर के रूप में किया जा सकता है। यह कुछ स्थितियों में बाइट्स को बचा सकता है जहां अंक और लोअरकेस अक्षरों की आवश्यकता नहीं होती है।

प्रश्न के अनुकूल कार्यान्वयन चुनें:

  • नकारात्मक कोशिकाएं लगभग हमेशा होती हैं उपयोगी होती हैं, और उनसे बचने का कोई कारण नहीं है (जब तक कि यह आपके बायटेकाउंट को नहीं बदलता है)
  • रैपिंग सेल के साथ लगभग एक ही बात, और भी अधिक क्योंकि कई स्थिरांक रैपिंग का उपयोग करते हैं।
  • मनमाने सेल क्रम अनंत गणित अनुक्रमों के लिए उपयोगी होते हैं, जैसे कि फाइबोनैचि अनुक्रम को असीम रूप से गणना करना ( +[[-<+>>+>+<<]>]), या बड़ी / नकारात्मक संख्याओं को संसाधित करना। नकारात्मक पक्ष यह है कि कुछ सामान्य विधियां, जैसे कि [-]और [->+<]पर भरोसा नहीं किया जा सकता है, बस संख्या नकारात्मक है।
  • EOF के रूप में 0, -1 या कोई परिवर्तन नहीं। 0 आमतौर पर बेहतर होता है, क्योंकि आप अतिरिक्त जांच के बिना पूरे इनपुट पर लूप कर सकते हैं। सरणी संरचनाओं पर लूपिंग करते समय -1 उपयोगी है। मुझे अभी तक कोई बदलाव नहीं मिला है :(

फ्रिक क्या चल रहा है, उस पर नज़र रखें:

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

किसी भी बिंदु पर, मेरा कोड इस तरह दिखने वाली हर दूसरी पंक्ति पर टिप्पणियों से अटा पड़ा है:

*0 *dat a_1 ?  0' !0 0*
 or
*0 *dat 0' ap1 0  !0 0*

कुछ अतिरिक्त सलाह प्रतीकों को विशेष अर्थ देने के लिए है। उपरोक्त उदाहरण में, 'पॉइंटर जहां है, *उस दिशा में पुनरावृत्ति का मतलब है, ?अज्ञात मान वाले सेल का !0अर्थ है, गैर-शून्य सेल, _इसका एक विकल्प है -और pइसका विकल्प है +orतात्पर्य यह है कि टेप या तो प्रतिनिधित्व की तरह लग सकता है, और इस तरह से संभाला जाना चाहिए।

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


5

सलाह का मेरा मुख्य टुकड़ा नहीं होगा।

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

मेमोरी एक्सेस भी बहुत महंगी है। चूंकि आप एक टेप से पढ़ रहे हैं, तो आपको यह ध्यान रखना होगा कि आपका सिर किसी भी समय पर घूम रहा है। अन्य भाषाओं जहां सिर्फ लिखने के विपरीत a, b, c, BF के में आप स्पष्ट रूप से, सिर कुछ बाइट्स से बाएं या दाएं स्थानांतरित करने के लिए ताकि आप जहाँ आप क्या स्टोर के प्रति जागरूक होना चाहिए है। मुझे पूरा यकीन है कि इष्टतम तरीके से अपनी मेमोरी को व्यवस्थित करना एनपी-कठिन है, इसलिए उस के साथ शुभकामनाएं।


5

इस उत्तर में मैं कई बार टेप पर एक विशिष्ट सेल का उल्लेख करने जा रहा हूँ। इससे कोई फर्क नहीं पड़ता कि यह कौन सी सेल है, लेकिन यह पूरे उत्तर भर में एक ही सेल है। इस पोस्ट के प्रयोजनों के लिए, मैं उस सेल को "टॉड" कहूंगा।

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

ब्रेनफक कॉन्स्टेंट्स के esolangs.org पेज के अनुसार (जो शायद अपने आप में एक टिप का विषय हो सकता है!) 30 पाने का सबसे छोटा तरीका है >+[--[<]>>+<-]>+। यह अग्रणी >केवल यह सुनिश्चित करने के लिए है कि सूचक के बाईं ओर कुछ भी संशोधित नहीं किया गया है, लेकिन इस मामले में हम मान लेंगे कि हम इस बारे में परवाह नहीं करते हैं और इसे छोड़ देते हैं। उस कोड का उपयोग करते हुए, आपका कोड कुछ इस तरह दिखाई देगा:

+[--[<]>>+<-]>+(MISC. CODE)(GO TO TODD)[.]

आप इस तरह से कोड का पहला हिस्सा सोच सकते हैं:

(SET TODD TO 30)(MISC. CODE)(GO TO TODD)[.]

लेकिन उस चंक में अंतिम दो पात्रों को याद रखें >+:। यह इस तरह से सोचना ही मान्य है:

(SET TODD TO 29)(GO TO TODD)(ADD 1 TO TODD)(MISC. CODE)(GO TO TODD)[.]

ध्यान दें कि आप (GO TO TODD)दो बार! आप इसके बजाय अपना कोड इस तरह से लिख सकते हैं:

(SET TODD TO 29)(MISC. CODE)(GO TO TODD)(ADD 1 TO TODD)[.]
+[--[<]>>+<-](MISC. CODE)(GO TO TODD)+[.]

यह मानते हुए कि बाइट्स की संख्या (GO TO TODD)पहले की ही है, एक कम चाल == एक कम बाइट! कभी-कभी यह तथ्य कि आपकी शुरुआती स्थिति बदल गई है, जो उस लाभ को दूर ले जाती है, लेकिन हमेशा नहीं।


0

इनपुट के बिना चुनौतियों के लिए एक छोटा सा टिप। आप ,इसके बजाय का उपयोग कर सकते हैं [-], यदि आपको सेल को जल्दी से साफ करने की आवश्यकता है, क्योंकि अधिकांश दुभाषियों (TIO.run एक सहित) सेल सामग्री को EOF प्रतिनिधित्व शून्य होने पर सेट करेगा। इससे प्रोग्राम थोड़ा छोटा होता है, लेकिन कोड गोल्फ में इसके बारे में कौन परवाह करता है?

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