गूढ़ भाषा 4DL

4DL का आविष्कार 2001 में क्लिफ एल। बिफले ने किया था। जैसा कि उन्होंने समझाया, उन्होंने सबसे पहले इसका आविष्कार किया, क्योंकि इससे पहले चार-आयामी कार्यक्रमों के साथ कोई भाषा नहीं थी, और दूसरी बात, क्योंकि चार-आयामी अंतरिक्ष को समझना काफी मुश्किल है, और आपको लोगों को अपने दिमाग को प्रशिक्षित करने का अवसर देने की आवश्यकता है।

रूसी विकिपीडिया इस भाषा को "फ़नगोइड" परिवार से संबंधित करता है। ये बेफुंज भाषा से उत्पन्न होने वाली भाषाएं हैं, ऐसे कार्यक्रम जिनमें एक आयताकार जाली पर पात्रों के रूप में लिखा जाता है और किसी भी दिशा में निष्पादित किया जा सकता है। 4DL में, एक चार-आयामी ग्रिड का उपयोग कार्यक्रम का प्रतिनिधित्व करने के लिए किया जाता है, और इसके निष्पादन की दिशाएं क्रमशः 8 हैं।

उदाहरण के लिए, 4DL कार्यक्रम इस तरह दिख सकता है:
X , B / \ B + 2 B - < ? TB - T y __ 10 __ __ 7 __ __ A __ __ __ __ 07 __ __ ------------------------------------------------------------------ __ Y __ __ __ __ __ __ __ __ . __ x __ __ x || __ __ __ __ __ __ __ __ __ __ 20 __ __ __ __ __ t X __ __ __ q + 2 q - < ? Z q - Z || z __ __ __ __ __ __ __ __ . b . x __ __ x 

यह कार्यक्रम "आधार" भाषा में नहीं लिखा गया है, बल्कि इसके विस्तार में है, लेकिन बाद में और अधिक।

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

4DL पर कार्यक्रम



यहाँ लेखक द्वारा प्रस्तावित कमांड सिस्टम है:
एक्सX + दिशा में कमांड पॉइंटर को घुमाएं
एक्सX- दिशा में कमांड को पॉइंटर चालू करें
YY + दिशा में कमांड पॉइंटर को घुमाएं
yY- दिशा में कमांड पॉइंटर को चालू करें
जेडZ + दिशा में सूचक को कमांड की ओर मोड़ें
zZ- दिशा में कमांड पॉइंटर को चालू करें
टीT + दिशा में कमांड पॉइंटर को चालू करें
टीT- की दिशा में सूचक को कमांड की ओर मोड़ें
पीX + से पड़ोसी सेल से प्रतीक को स्टैक पर रखें
पीसाइड X से पड़ोसी सेल से प्रतीक को स्टैक पर रखें-
बीY + की ओर से पड़ोसी सेल से प्रतीक को ढेर पर रखें
स्टैक पर साइड Y- से एक पड़ोसी सेल से एक प्रतीक रखो
डीस्टैक पर जेड + की तरफ एक पड़ोसी सेल से एक प्रतीक रखो
साइड Z से पड़ोसी सेल से प्रतीक को स्टैक पर रखें-
क्यूसाइड टी + से पड़ोसी सेल से प्रतीक को स्टैक पर रखें
क्षस्टैक पर टी की तरफ एक पड़ोसी सेल से एक प्रतीक रखो
+स्टैक के शीर्ष पर दो संख्याओं का योग लें, परिणाम को स्टैक पर रखें
-स्टैक के शीर्ष पर दो संख्याओं का अंतर लें, परिणाम को स्टैक पर रखें
कीबोर्ड से एक चरित्र दर्ज करें और इसे स्टैक पर रखें
स्टैक और प्रदर्शन के शीर्ष से एक चरित्र खींचो
#कार्यक्रम के अगले सेल पर कूदें
?स्टैक के शीर्ष से संख्या निकालें, और यदि यह नोनज़रो है, तो प्रोग्राम के अगले सेल पर कूदें
0नंबर 0 को स्टैक पर रखें
2इसके शीर्ष पर संख्या की एक प्रति स्टैक पर रखें
%एक कार्यक्रम समाप्त करें


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

\स्टैक के शीर्ष पर दो कोशिकाओं की सामग्री को स्वैप करें
^स्टैक के शीर्ष से एक नंबर निकालें और इसके साथ कुछ भी न करें (2- + या? XX के बराबर - यदि दाईं ओर बढ़ रहा है)


जिंदगी और ज्यादा मजेदार हो गई है। उदाहरण के लिए, यहां एक प्रोग्राम ऐसा दिखता है जो इनपुट स्ट्रिंग से संख्याओं का योग प्रिंट करता है:
  0 X , D - 2 ? TD - 2 ? TD - Y || __ z __ 0D __ __ __ __ 13 __ __ __ __ 10 __ __ YDT ? 2 - DT ? 2 - D , x || __ __ __ 10 __ __ __ __ 13 __ __ __ __ 0D __ __ X - \ 2 2 + 2 + + 2 + + __ y ------------------- T t __ __ __ __ __ ^ __ __ __ __ x || __ t + y + ^ x __ __ __ __ ^ || __ y __ __ . B . B x D || 01 __ __ __ __ 0A __ 0D y \ + x __ X __ y ------------------- Y 0 x \ 0 ^ , x + x || __ __ __ __ __ Y __ __ . x \ __ y Z ? 2 \ - xy || __ __ __ X + X 2 ? ty D __ __ __ X + D \ y || 0A __ __ __ __ __ 3A X \ 2 ? y D - Y || __ __ __ __ __ 01 yt ? 2 - D \ x || __ __ __ __ __ 01 


कार्यक्रम की रिकॉर्डिंग के बारे में कुछ शब्द (ये पहले से ही मेरी कल्पनाएं हैं - लेखक ने किसी भी तरह से इनपुट सिंटैक्स का वर्णन नहीं किया है)।

जिस स्थान पर कार्यक्रम स्थित है, उसे दो-आयामी परतों में विभाजित किया गया है, जिसमें निर्देशांक Z और T स्थिर हैं। प्रत्येक परत के प्रतीकों को आयताकार तालिका के रूप में लिखा जाता है, जो कोण X = Y = 0 से शुरू होता है। यदि यह ASCII-7 (33 से 126 के कोड के साथ) का एक चरित्र है, तो यह स्पष्ट रूप से लिखा जाता है। यदि नहीं, तो इसका दो अंकों वाला हेक्साडेसिमल कोड लिखा है। एक स्थान 20 या डबल अंडरस्कोर के रूप में निर्दिष्ट किया जा सकता है। किसी भी स्थान के माध्यम से वर्ण लिखे जाते हैं, उनके साथ एक रेखा एक स्थान से शुरू होती है।

आयतों को एक दो-आयामी तालिका में जोड़ा जाता है। क्षैतिज रूप से T के समान मान के साथ परतें हैं (क्रमिक रूप से: Z = 0, Z = 1, ...), ऊर्ध्वाधर - Z के समान मान वाले स्तंभ। परतों में लाइनों की लंबाई, एक परत में लाइनों की संख्या, एक तालिका पंक्ति में परतों की संख्या भिन्न हो सकती है। - गायब कोशिकाओं को कोड के साथ वर्णों से भरा जाएगा। तालिका पंक्ति में परतें वर्णों से अलग हो जाती हैं || और रेखाएँ स्वयं एक ऋण से शुरू होने वाली रेखाएँ हैं।

डिफ़ॉल्ट रूप से, एक्स + दिशा में सेल (0,0,0,0) से निष्पादन शुरू होता है। प्रारंभिक बिंदु को स्ट्रिंग> x, y, z, t (संख्या x, y, z और t दशमलव) को प्रोग्राम में सम्मिलित करके पुनर्परिभाषित किया जा सकता है।

4-आयामी स्थान में उपरोक्त कार्यक्रम का निष्पादन पथ कुछ इस तरह दिखता है:

उन कोशिकाओं के अलावा जिनके माध्यम से लाल रेखा गुजरती है, डेटा के साथ कुछ और कोशिकाएं हैं, लेकिन मैंने उन्हें प्रदर्शित नहीं करने का फैसला किया।

ट्यूरिंग पूरा है या नहीं?


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

किसी भी मामले में, कार्यक्रम की चार-आयामीता लगभग कभी भी उपयोग नहीं की जाती है, और किसी भी 4DL कार्यक्रम को दो-आयामी स्थान में एम्बेड किया जा सकता है। इसके अलावा, डेटा के लिए निष्पादन योग्य कोड, Y = 1 के लिए लाइन Y = 0 को छोड़ दें और संक्रमण आदेशों को लागू करने के लिए विमान के बाकी हिस्सों का उपयोग करें। यह विकल्प निर्बाध लगता है।

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

4DL + और ट्यूरिंग मशीन


4 डीएल भाषा के कार्यान्वयन में से एक के लेखक द्वारा एक अधिक मध्यम संस्करण प्रस्तावित किया गया था - बर्नहार्ड स्टोकेनर। इसके कार्यान्वयन के लिए कमांड की "विस्तारित" प्रणाली में, वह अन्य चीजों के साथ, निम्नलिखित कमांड प्रदान करता है:
एनX + की ओर से एक चरित्र को ढेर से एक आसन्न कक्ष में रखें
nस्टैक से एक प्रतीक को बगल के सेल से X में रखें-
एफY + की ओर से बगल के सेल में स्टैक से एक पात्र रखो
स्टैक से Y- ओर से सटे सेल में एक प्रतीक रखो
जीZ + की ओर से एक चरित्र को ढेर से एक आसन्न कक्ष में रखें
जीबगल से सेल में स्टैक से एक प्रतीक रखें Z-
एचT + की तरफ से सटे सेल में स्टैक से एक प्रतीक रखो
स्टैक से एक प्रतीक को T की ओर से एक आसन्न सेल में रखें।

यह पता चलता है कि ट्यूरिंग भाषा को 8-बिट स्टैक सेल (32-बिट का उल्लेख नहीं करने के लिए भी) के साथ पूरा करने के लिए ये कमांड पर्याप्त हैं। यह साबित करने के लिए, आइए सबसे सरल तरीके से चलते हैं - हम एक ट्यूरिंग मशीन लागू करेंगे :)

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

पहला विचार एक "गगनचुंबी इमारत" के रूप में टेप को लागू करने का था, जिसमें प्रत्येक मंजिल "टेप सेल को पढ़ने", "सेल की सामग्री को बदलने", "ऊपर ले जाने" और "नीचे जाने" के आदेशों का समर्थन कर सकती थी, और जब यह शीर्ष पर पहुंच गया - निर्माण शुरू करें साइट ”, जो एक नई मंजिल के निर्माण के लिए वास्तविकता की एक समानांतर परत में बढ़ती है। समस्या हल हो गई, लेकिन जल्दी से एक बहुत आसान तरीका खोजने में कामयाब रहे।

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

उदाहरण के लिए, अनुक्रम [एन, एक्स, एक्स, एन] लाइन को चालू करता है
 __ __ __ __ एन

लाइन में
 __ __ __ __ एनएन एक्स

और अगर इसके बाद हम इस पंक्ति को अनुक्रम [n, n, n, N, n] भेजते हैं, तो हमें रेखा मिलती है
 __ __ __ एन nnx

- सबसे बाईं ओर "N" सेल के बाईं ओर जाएगा। इसी तरह, दो चरणों में आप "सही कदम", "अगली पंक्ति के लिए एक चरित्र लिखें" और "अगली पंक्ति से चरित्र पढ़ें" को निष्पादित कर सकते हैं। सेल के दाईं ओर स्थित दो पदों पर स्थित सेल के साथ काम करना सबसे सुविधाजनक है जिसमें "एन" कमांड स्थित है।

ट्यूरिंग मशीन को लागू करने वाले कार्यक्रम में तीन भाग होंगे। लेयर टी = 0 का उपयोग कार्यक्रम और टेप के बीच संचार के लिए किया जाएगा। कार्यक्रम क्षेत्र में होगा T> 0, Z = 0 और एक परिमित राज्य मशीन होगी (मेमोरी के साथ) जो टेप पर वर्तमान चरित्र को एक जोड़ी (नए चरित्र, पारी दिशा) में परिवर्तित करती है। हम टेप को Y = Z = T = 1 लाइन पर रखते हैं, और नियंत्रण कार्यक्रम T> 0, Z = 1 क्षेत्र पर कब्जा कर लेगा। टेप इंटरफ़ेस प्रोग्राम इंटरफ़ेस को पूरक करता है: एक जोड़ी (प्रतीक, शिफ्ट दिशा) में, यह टेप की सामग्री को बदलता है, गाड़ी को शिफ्ट करता है, और एक नया चरित्र देता है जो गाड़ी को इंगित करता है।

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

कार्यक्रम की वर्तमान स्थिति कोड संशोधन का उपयोग करके संग्रहीत की जाती है। प्रसंस्करण करने के लिए, नियंत्रण टी + दिशा में बिंदु (2,3,0,1) पर स्थानांतरित किया जाता है, और "टी" कमांड से भरी सीधी रेखा में जाता है, जिसमें वर्तमान स्थिति के अनुरूप एक सेल होता है। इस सेल में कमांड "x" (बाएं जाएं) है। कार्यक्रम "सही मंजिल पर बाहर निकलता है", "एक्स" कमांड को "टी" में बदल देता है, फिर स्टैक के शीर्ष पर प्रतीक का विश्लेषण करता है, आंदोलन की वांछित दिशा और स्टैक पर एक नया प्रतीक डालता है, जिसके बाद यह "मंजिल" के समान हो जाता है, जो साइड ट्रैक्स के माध्यम से नई स्थिति के अनुसार होता है, सेल में "x" कमांड डालता है (2,3,0, T) और प्लेन Z = T = 0 पर जाता है, जहाँ इसे टेप को नियंत्रित करने के लिए भेजा जाता है।

दरअसल, बस इतना ही। यहां एक उदाहरण कार्यक्रम है जो टेप पर दर्ज संख्या के दोहरीकरण को लागू करता है। कार्यक्रम में 7 राज्य हैं, टेप पर अब नंबर 2 (दो यूनिट) है।
कार्यक्रम
  B __ Y || TX 2 Y 01 __ __ || __ __ __ P 0 __ __ __ || y \ . + b 2 x __ __ T . B x || __ __ 0 X . z __ Z __ __ __ __ || X 2 b + . \ y -------------------------------------------------------------------------------- __ __ __ __ __ 02 01 __ __ __ __ || Y t X # ? __ # \ __ __ N __ __ __ __ T __ __ X bb __ __ __ Y || __ __ T __ __ __ __ __ __ __ FF 00 01 01 00 X b F ? y BBY __ __ __ || N __ p y __ xx __ 02 00 T __ YT || __ __ y t __ fb __ __ __ __ __ x __ || __ __ T || N __ p || __ __ y __ __ __ __ __ __ __ __ x || XQQQQQQQQQQ y -------------------------------------------------------------------------------- __ __ __ __ __ 02 00 __ __ __ __ || __ __ t __ __ __ __ __ __ __ __ x __ T __ __ X bb __ Y __ __ || __ __ XBBBBBBBB y X b F ? y BBY __ __ __ || __ __ __ 01 # # F xx NN y __ T x __ 02 01 YT __ __ || __ __ __ t __ fb __ __ __ x __ __ __ || __ __ 2 || __ __ __ || __ __ __ || __ 00 01 # # B xx N 01 N -------------------------------------------------------------------------------- __ __ __ __ __ 01 01 __ __ __ __ || __ T __ __ X bb Y __ __ __ || X b F ? y BB __ Y __ __ || y __ T x __ 02 01 TY __ __ || __ __ __ t __ fb __ __ __ __ x __ __ || __ __ ? -------------------------------------------------------------------------------- __ __ __ __ __ 01 00 __ __ __ __ || __ T __ __ X bb __ Y __ __ || X b F ? y BBY __ __ __ || y __ T x __ 01 01 YT __ __ || __ __ t __ x t __ fb __ __ __ x __ __ __ || __ __ X ^ y -------------------------------------------------------------------------------- __ __ __ __ __ 02 01 __ __ __ __ || __ T __ __ X bb __ __ Y __ || X b F ? y BB __ Y __ __ || y __ T x __ 01 01 __ Y t __ || __ __ __ t __ fb __ __ __ __ x __ __ || __ __ P 01 -------------------------------------------------------------------------------- __ __ __ __ __ 01 00 __ __ __ __ || __ T __ __ X bb Y __ __ __ || X b F ? y BB __ __ __ Y || y __ T x __ 02 01 T __ __ Y || __ __ __ t __ fb __ __ __ __ __ __ x || __ __ - -------------------------------------------------------------------------------- __ __ __ __ __ __ __ __ __ __ __ || __ T __ __ % __ __ __ __ __ __ || X b F ? y BBY __ __ __ || y __ T x __ 00 00 Y __ __ __ || __ __ __ t __ fb __ __ __ x __ __ __ || __ __ ? -------------------------------------------------------------------------------- || || || __ __ __ __ N 01 xx N || __ __ t __ bbbbbx || __ __ XBBBBBB y || __ __ __ n N nn 01 n -------------------------------------------------------------------------------- || || || __ __ __ __ N 01 N xxn || __ __ t __ bbbbbbx || __ __ XBBBBBBB y || __ __ __ NNN __ 01 nn 


यदि आप इस प्रोग्राम को चलाते हैं, तो यह प्रिंट होगा
 021 120 020 110 011 110 121 020 021 120 111 110 010 120 121 121 120 120 011 000

प्रत्येक ट्रिपल अक्षर एक नया चरित्र है जिसे टेप (0 या 1) पर छोड़ा जाना चाहिए, वह दिशा जहां स्थानांतरित करना है (0 - जगह में, 1 - बाईं ओर, 2 - दाईं ओर) और एक चरित्र जो गाड़ी की नई स्थिति के तहत है। आप सत्यापित कर सकते हैं कि कार्यक्रम ने सब कुछ सही किया, और परिणाम 4 है।

कुछ प्रयासों के साथ, यह कार्यान्वयन 2 डी में भी फिट हो सकता है। लेकिन 4 आयामों में, काम करना थोड़ा अच्छा है - बहुत अधिक स्वतंत्रता।

आगे क्या है?


आप भाषा का थोड़ा विस्तार कर सकते हैं - शेष के साथ गुणा की आज्ञाओं को जोड़ सकते हैं, और संख्या को स्टैक पर धकेल सकते हैं (स्मृति के लिए लिखने के लिए बाइट में संख्या के अधिक सुविधाजनक विभाजन के लिए)। सच है, नकारात्मक संख्याओं के साथ समस्याएं होंगी। 256 के बजाय, आप "लो बाइट को विभाजित करें" ([x] => [x & 0xff, x >> 8]) और "लो बाइट पेस्ट करें" ([x, y] => [x + (y [8)]) को जोड़ सकते हैं। लेकिन यह केवल अपने सार को बदले बिना भाषा को अधिक सुविधाजनक बना देगा। यह देखना अधिक दिलचस्प है कि भाषा में क्या अतिशयोक्ति है, और बहुआयामी स्मृति का उपयोग करने के लिए कितना अच्छा है।

उदाहरण के लिए:

वैसे, एसॉलंग पर एक युगल अधिक चार-आयामी (अधिक सटीक, बहुआयामी) भाषाओं की खोज की गई थी। दोनों BrainFuck बोलियाँ हैं। लेकिन एक में, गाड़ी बहुआयामी मेमोरी के माध्यम से भटकती है, और प्रोग्राम बीएफ पर एक पंक्ति की तरह दिखता है, और दूसरे तरीके से - कार्यक्रम बहुआयामी है, लेकिन स्मृति रैखिक है। 4 डीएल से अंतर यह है कि दोनों मामलों में प्रबंधन और मेमोरी के साथ काम अलग-अलग हैं।

संदर्भ।


एसोलंग पर 4 डीएल पेज
लेखक के ब्लॉग से पेज
दुभाषिया स्थल
Befunge और इसकी बोलियाँ
बहुआयामी स्मृति के साथ दिमाग
एक बहुआयामी कार्यक्रम के साथ दिमाग लगाना

Source: https://habr.com/ru/post/In170875/


All Articles