हफ्तों भर की उत्सुकता के बाद, आप और आपके दोस्त पहली बार Dungeons & Dragons (D&D) खेलने के लिए इकट्ठा हुए। चूँकि यह खेल का पहला ही दौर है, हर खिलाड़ी को अपने लिए एक पात्र बनाना होता है। पात्र की क्षमताएँ छह फलकों वाला पासा फेंककर तय की जाती हैं। लेकिन पासे कहाँ हैं?
आपको झटका तब लगता है जब पता चलता है कि आपके दोस्त पासे जुटाने के लिए आपका ही इंतज़ार कर रहे हैं। D&D खेलने का विचार तो आपका ही था!
घबराहट में आपको याद आता है कि आप पासे लाना भूल ही गए हैं। और पासे न हों, तो D&D का खेल नहीं हो पाएगा। चूँकि आपको कोडिंग की थोड़ी बुनियादी जानकारी है, आप तुरंत एक हल निकाल लेते हैं: आप एक प्रोग्राम लिखेंगे जो पासा फेंकने की नकल करेगा।
Dungeons & Dragons के खेल में हर खिलाड़ी सबसे पहले एक पात्र बनाता है और फिर उसी के साथ खेलता है। इस पात्र में और भी कई चीज़ें होती हैं, जिनमें छह क्षमताएँ भी हैं: strength, dexterity, constitution, intelligence, wisdom और charisma। इन छह क्षमताओं के स्कोर यादृच्छिक तरीके से तय होते हैं। इसके लिए आप छह फलकों वाले चार पासे फेंकते हैं और सबसे बड़े तीन पासों का जोड़ लिख लेते हैं। ऐसा आप छह बार करते हैं, हर क्षमता के लिए एक बार।
खेल की शुरुआत में आपके पात्र के hitpoints 10 में उसके constitution मॉडिफायर को जोड़कर निकलते हैं। अपने पात्र का constitution मॉडिफायर निकालने के लिए उसके constitution में से 10 घटाइए, फिर 2 से भाग दीजिए और नीचे की ओर पूर्णांकित कीजिए।
ऊपर बताए नियमों का पालन करने वाला एक यादृच्छिक पात्र जनरेटर लिखिए।
उदाहरण के लिए, चार पासों को छह बार फेंकने पर नतीजे कुछ ऐसे आ सकते हैं:
चूँकि constitution 3 है, इसलिए constitution मॉडिफायर -4 होता है और hitpoints 6 होते हैं।
अधिकांश प्रोग्रामिंग भाषाओं में (छद्म-)यादृच्छिक जनरेटर होते हैं, लेकिन कम ही प्रोग्रामिंग भाषाएँ पासा फेंकने के लिए बनाई गई हैं। ऐसी ही एक भाषा Troll है।
फंक्शनल भाषाओं में अधिकांश फंक्शन प्योर होते हैं। इसका मतलब है कि आर्गुमेंट का एक ही समूह मिलने पर वे हमेशा एक ही आउटपुट लौटाते हैं, और इसके अलावा कुछ नहीं करते। दूसरे शब्दों में, प्योर फंक्शन नियतात्मक होते हैं।
लेकिन परिभाषा के अनुसार यादृच्छिक वैल्यू का पहले से अनुमान नहीं लगाया जा सकता और वह अनियतात्मक होती है। यहाँ तक कि छद्म-यादृच्छिकता, यानी संख्याओं का ऐसा क्रम लौटाना जो यादृच्छिक लगता हो, प्योर तरीके से कर पाना भी इतना आसान नहीं है। इसका कारण यह है कि छद्म-यादृच्छिक संख्या जनरेटर (PRNG) को क्रम की अगली संख्या लौटाने के लिए अपनी आंतरिक स्थिति बनाए रखनी पड़ती है।
Lean इस समस्या के लिए दो तरीके देता है:
ऐसा मोनाड इस्तेमाल कीजिए जिससे PRNG की आंतरिक स्थिति बदलना संभव हो।
इसके लिए पहले से एक फंक्शन IO.rand मौजूद है, जो ठीक यही काम करता है।
ऐसे प्योर फंक्शन इस्तेमाल कीजिए जो एक जनरेटर को आर्गुमेंट की तरह लेते हैं और सिर्फ बनी हुई छद्म-यादृच्छिक वैल्यू ही नहीं, बल्कि क्रम की अगली संख्या के लिए "तैयार" अद्यतन जनरेटर भी लौटाते हैं।
यह अभ्यास दूसरा तरीका इस्तेमाल करता है। हर उस फंक्शन को एक जनरेटर दिया जाता है जिसे छद्म-यादृच्छिक वैल्यू बनानी होती है, और उस फंक्शन से यह अपेक्षा की जाती है कि वह वैल्यू के साथ अद्यतन जनरेटर भी लौटाए।
ध्यान रखिए कि कोई भी दिया गया जनरेटर नियतात्मक होता है, यानी वह हमेशा एक ही वैल्यू बनाता है। क्रम में अगली छद्म-यादृच्छिक वैल्यू बनाने के लिए अद्यतन जनरेटर ही इस्तेमाल करना पड़ता है।
इस अभ्यास में यादृच्छिकता की जाँच p < 0.0001 के सार्थकता स्तर पर काई-वर्ग परीक्षण से की जाती है।
इसका मतलब है कि अगर निर्देशों के अनुसार एबिलिटी स्कोर बनाया जाए, तो किसी सही कार्यान्वयन के सिर्फ यादृच्छिक संयोग से टेस्ट में फेल होने की संभावना 0.01% से भी कम है।
ध्यान रखिए कि निर्देशों के अनुसार एबिलिटी स्कोर एक निष्पक्ष d6 (छह फलकों वाला पासा) को चार बार फेंककर मिले नतीजों में से तीन सबसे बड़े नतीजों का जोड़ होता है।
Exercism पर साइन अप कीजिए और Lean को 100 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।
हम देखेंगे कि (दिखने में) बेतरतीब पासे कैसे रोल किए जाएँ। आप सीड, स्यूडो रैंडम संख्याओं और कुछ आम गलतियों के बारे में जानेंगे। अंत में, हम देखेंगे कि बेतरतीब वैल्यू लौटाने वाले फंक्शन की जाँच के लिए प्रॉपर्टी-आधारित टेस्टिंग बढ़िया है।