गोल्फस्क्रिप्ट - 12 वर्ण
{,1\{)*}/}:f
गोल्फस्क्रिप्ट के साथ शुरुआत करना - कदम-कदम पर फैक्टरियल
यहां उन लोगों के लिए कुछ है जो गोल्फस्क्रिप्ट सीखने की कोशिश कर रहे हैं। पूर्वापेक्षा गोल्फस्क्रिप्ट की एक बुनियादी समझ है, और गोल्फस्क्रिप्ट दस्तावेज़ पढ़ने की क्षमता।
इसलिए हम अपने नए टूल गोल्फस्क्रिप्ट को आज़माना चाहते हैं । कुछ सरल से शुरू करना हमेशा अच्छा होता है, इसलिए हम तथ्य के साथ शुरुआत कर रहे हैं। यहाँ एक प्रारंभिक कोशिश है, जो एक साधारण अनिवार्य छद्मकोश पर आधारित है:
# pseudocode: f(n){c=1;while(n>1){c*=n;n--};return c}
{:n;1:c;{n 1>}{n c*:c;n 1-:n;}while c}:f
व्हॉट्सएप का उपयोग बहुत कम ही गोल्फ में होता है। व्हाट्सएप से छुटकारा पाने के लिए सबसे आसान ट्रिक है विभिन्न वेरिएबल नामों का उपयोग करना। प्रत्येक टोकन को एक चर के रूप में इस्तेमाल किया जा सकता है ( वाक्यविन्यास पृष्ठ देखें )। उपयोगी टोकन के रूप में चर की तरह विशेष वर्णों को उपयोग करने के लिए |
, &
, ?
आम तौर पर कुछ भी नहीं कोड में कहीं और इस्तेमाल किया -। इन्हें हमेशा सिंगल कैरेक्टर टोकन के रूप में रखा जाता है। इसके विपरीत, चर की तरह n
एक संख्या के बाद ढेर को धकेलने के लिए स्थान की आवश्यकता होगी। संख्याएं अनिवार्य रूप से पूर्व-निर्धारित चर हैं।
हमेशा की तरह, ऐसे कथन होने जा रहे हैं जिन्हें हम अंतिम परिणाम को प्रभावित किए बिना बदल सकते हैं। Golfscript में, सब कुछ को छोड़कर सही का आकलन 0
, []
, ""
, और {}
(देखें इस )। यहां, हम लूप निकास स्थिति को बस में बदल सकते हैं {n}
(हम एक अतिरिक्त समय लूप करते हैं, और जब n = 0 समाप्त होता है)।
किसी भी भाषा को गोल्फ के साथ उपलब्ध कार्यों को जानने में मदद करता है। सौभाग्य से यह सूची गोल्फस्क्रिप्ट के लिए बहुत कम है। हम एक और चरित्र को बचाने के 1-
लिए बदल सकते हैं (
। वर्तमान में कोड इस तरह दिखता है: (हम प्रयोग किया जा सकता है 1
के बजाय |
यहां अगर हम चाहते थे, जो प्रारंभ छोड़ देगी।)
{:n;1:|;{n}{n|*:|;n(:n;}while|}:f
सबसे कम समाधान (अभ्यास अभ्यास अभ्यास) प्राप्त करने के लिए स्टैक का उपयोग करना महत्वपूर्ण है। आमतौर पर, यदि मान केवल कोड के एक छोटे खंड में उपयोग किए जाते हैं, तो उन्हें चर में संग्रहीत करना आवश्यक नहीं हो सकता है। चल रहे उत्पाद चर को हटाकर और केवल स्टैक का उपयोग करके, हम काफी पात्रों को बचा सकते हैं।
{:n;1{n}{n*n(:n;}while}:f
यहाँ कुछ और सोचने के लिए है। हम n
लूप बॉडी के अंत में स्टैक से वैरिएबल को हटा रहे हैं , लेकिन फिर इसे तुरंत बाद धकेल रहे हैं। वास्तव में, लूप शुरू होने से पहले हम इसे स्टैक से भी निकालते हैं। हमें इसके बजाय इसे स्टैक पर छोड़ देना चाहिए, और हम लूप की स्थिति को खाली रख सकते हैं।
{1\:n{}{n*n(:n}while}:f
शायद हम चर को पूरी तरह से खत्म भी कर सकते हैं। ऐसा करने के लिए, हमें हर समय वैरिएबल को स्टैक पर रखना होगा। इसका मतलब है कि हमें स्थिति की जांच के अंत में स्टैक पर चर की दो प्रतियों की आवश्यकता है ताकि हम इसे चेक के बाद खो न दें। जिसका अर्थ है कि हम 0
लूप के समाप्त होने के बाद स्टैक पर निरर्थक होंगे , लेकिन इसे ठीक करना आसान है।
यह हमें हमारे इष्टतम while
लूप समाधान की ओर ले जाता है !
{1\{.}{.@*\(}while;}:f
अब हम इसे छोटा करना चाहते हैं। स्पष्ट लक्ष्य शब्द होना चाहिए while
। प्रलेखन को देखते हुए, दो व्यवहार्य विकल्प हैं - प्रकट करना और करना । जब आपके पास दोनों के लाभों को लेने, प्रयास करने और वजन करने के लिए विभिन्न मार्गों का विकल्प होता है। अनफोल्ड 'बहुत अधिक समय तक लूप' है, इसलिए एक अनुमान के रूप में हम 5 चरित्र while
को 4 से कम कर देंगे /
। के रूप में do
, हम while
3 वर्णों में कटौती करते हैं , और दो ब्लॉकों को मर्ज करने के लिए मिलता है, जो एक और चरित्र या दो को बचा सकता है।
do
लूप का उपयोग करने में वास्तव में एक बड़ी खामी है । चूंकि शरीर द्वारा एक बार निष्पादित किए जाने के बाद हालत की जांच की जाती है, इसलिए मूल्य 0
गलत होगा, इसलिए हमें एक बयान की आवश्यकता हो सकती है। मैं अब आपको बताता हूं कि अनफॉल्ड कम है (कुछ समाधान do
अंत में दिए गए हैं)। आगे बढ़ो और इसे आज़माओ, हमारे पास पहले से मौजूद कोड में न्यूनतम बदलाव की आवश्यकता है।
{1\{}{.@*\(}/;}:f
महान! हमारा समाधान अब सुपर-शॉर्ट हो गया है और हम यहीं पर हैं? नहीं। यह 17 वर्ण है, और J में 12 वर्ण हैं। हार कभी न मानें!
अब आप सोच रहे हैं ... पुनरावृत्ति
पुनरावर्तन का उपयोग करने का मतलब है कि हमें एक शाखा संरचना का उपयोग करना चाहिए । दुर्भाग्यपूर्ण, लेकिन जैसा कि तथ्यात्मक रूप से इतने संक्षिप्त रूप से व्यक्त किया जा सकता है, यह पुनरावृत्ति के लिए एक व्यवहार्य विकल्प जैसा लगता है।
# pseudocode: f(n){return n==0?n*f(n-1):1}
{:n{n.(f*}1if}:f # taking advantage of the tokeniser
खैर यह आसान था - क्या हमने पहले पुनरावृत्ति की कोशिश की थी, हम एक while
लूप का उपयोग करने पर भी ध्यान नहीं दे सकते थे ! फिर भी, हम केवल 16 वर्णों पर हैं।
Arrays
ऐरे आम तौर पर दो तरीकों से बनाए जाते हैं - [
और ]
वर्णों का उपयोग करके , या ,
फ़ंक्शन के साथ । यदि स्टैक के शीर्ष पर एक पूर्णांक के साथ निष्पादित किया जाता है, तो ,
गिरफ्तारी [i] = i के साथ उस लंबाई की एक सरणी देता है।
सरणियों पर पुनरावृत्ति के लिए, हमारे पास तीन विकल्प हैं:
{block}/
: धक्का, ब्लॉक, धक्का, ब्लॉक, ...
{block}%
: [धक्का, ब्लॉक, धक्का, ब्लॉक, ...] (यह कुछ बारीकियों है, उदाहरण के लिए मध्यवर्ती मूल्यों को प्रत्येक से ढेर से हटा दिया जाता है)
{block}*
: धक्का, धक्का, ब्लॉक, धक्का, ब्लॉक, ...
गोल्फस्क्रिप्ट प्रलेखन में {+}*
एक सरणी की सामग्री का योग करने का एक उदाहरण है । इससे पता चलता है कि हम {*}*
किसी सरणी का उत्पाद प्राप्त करने के लिए उपयोग कर सकते हैं ।
{,{*}*}:f
दुर्भाग्य से, यह इतना आसान नहीं है। सभी तत्व एक के [0 1 2]
बजाय एक (बंद [1 2 3]
) हैं। हम {)}%
इस समस्या को सुधारने के लिए उपयोग कर सकते हैं ।
{,{)}%{*}*}:f
खैर काफी नहीं। यह शून्य को सही तरीके से नहीं संभालता है। हम इसे सुधारने के लिए (n + 1)! / (N + 1) की गणना कर सकते हैं, हालांकि यह बहुत अधिक लागत है।
{).,{)}%{*}*\/}:f
हम n = 1 के रूप में एक ही बाल्टी में n = 0 को संभालने की भी कोशिश कर सकते हैं। यह आपके द्वारा किए गए सबसे कम समय के लिए करने, प्रयास करने और काम करने के लिए वास्तविक अत्यंत छोटा है।
इतना अच्छा नहीं है, 7 अक्षरों में: छँटाई [1\]$1=
। ध्यान दें कि इस सॉर्टिंग तकनीक में उपयोगी उद्देश्य होते हैं, जैसे कि किसी संख्या पर सीमाएं लगाना (जैसे `[0 \ 100] $ 1 =)
यहाँ विजेता केवल 3 वर्णों के साथ है:! +!
यदि हम एक ही ब्लॉक में वृद्धि और गुणा करना चाहते हैं, तो हमें सरणी में प्रत्येक तत्व पर पुनरावृति करना चाहिए। चूँकि हम कोई सरणी नहीं बना रहे हैं, इसका मतलब है कि हमें इसका उपयोग करना चाहिए {)*}/
, जो हमें सबसे छोटे गोल्फस्प्रेक्टर को फैक्टरियल के कार्यान्वयन में लाता है! 12 वर्णों पर, यह J से बंधा है!
{,1\{)*}/}:f
बोनस समाधान
if
एक do
लूप के लिए एक सीधा समाधान के साथ शुरू :
{.{1\{.@*\(.}do;}{)}if}:f
हम इसमें से एक जोड़े को निचोड़ सकते हैं। थोड़ा जटिल है, इसलिए आपको खुद को इन कामों के लिए राजी करना होगा। सुनिश्चित करें कि आप इन सभी को समझते हैं।
{1\.!!{{.@*\(.}do}*+}:f
{.!{1\{.@*\(.}do}or+}:f
{.{1\{.@*\(.}do}1if+}:f
एक बेहतर विकल्प गणना (एन + 1) है! / (एन + 1), जो एक if
संरचना की आवश्यकता को समाप्त करता है ।
{).1\{.@*\(.}do;\/}:f
लेकिन यहां सबसे छोटा do
समाधान 0 से 1 के नक्शे तक कुछ वर्णों को ले जाता है, और बाकी सब अपने आप को - इसलिए हमें किसी शाखा की जरूरत नहीं है। इस तरह का अनुकूलन याद करने में बेहद आसान है।
{.!+1\{.@*\(.}do;}:f
रुचि रखने वाले किसी व्यक्ति के लिए, ऊपर की लंबाई के साथ कुछ वैकल्पिक पुनरावर्ती समाधान यहां दिए गए हैं:
{.!{.)f*0}or+}:f
{.{.)f*0}1if+}:f
{.{.(f*}{)}if}:f
* नोट: मैंने वास्तव में इस पोस्ट में कोड के कई टुकड़ों का परीक्षण नहीं किया है, इसलिए यदि कोई त्रुटि हो तो सूचित करें।