ट्रैक
/
Elixir
Elixir
/
अभ्यास
/
नंबर से रंग भरिए
नंबर से रंग भरिए

नंबर से रंग भरिए

सीखने का अभ्यास

परिचय

बिटस्ट्रिंग

बाइनरी डेटा के साथ काम करना हर भाषा में एक महत्वपूर्ण कॉन्सेप्ट है। Elixir बाइनरी डेटा को लिखने, मैच करने और बनाने के लिए एक सुंदर सिंटैक्स देता है।

Elixir में बाइनरी डेटा को बिटस्ट्रिंग टाइप कहा जाता है। बाइनरी डेटा टाइप (सामान्य बाइनरी डेटा से इसे भ्रमित न कीजिए) बिटस्ट्रिंग का ही एक खास रूप है। इस पर हम बाद के किसी अभ्यास में बात करेंगे।

बिटस्ट्रिंग लिटरल बिटस्ट्रिंग के स्पेशल फॉर्म <<>> की मदद से बनाए जाते हैं। बिटस्ट्रिंग लिटरल लिखते समय उसे सेगमेंट में बाँटा जाता है। हर सेगमेंट में एक वैल्यू और एक टाइप होता है, जिन्हें :: ऑपरेटर से अलग किया जाता है। टाइप बताता है कि वैल्यू को एनकोड करने के लिए कितने बिट इस्तेमाल होंगे। टाइप को पूरी तरह छोड़ा भी जा सकता है, और तब डिफॉल्ट रूप से 8-बिट पूर्णांक वैल्यू मानी जाती है।

# This defines a bitstring with three segments of a single bit each
<<0::1, 1::1, 0::1>>

टाइप को ::1 लिखना ::size(1) लिखने का छोटा रूप है। अगर बिट का साइज़ किसी वेरिएबल से आ रहा हो, तो आपको लंबा सिंटैक्स इस्तेमाल करना होगा।

बाइनरी

बाइनरी पूर्णांक लिटरल लिखते समय हम उन्हें सीधे बेस-2 संकेतन में लिख सकते हैं, बस लिटरल से पहले 0b लगा दीजिए। ध्यान रखिए कि टेस्ट के परिणामों में या iex इस्तेमाल करते समय ये वैसे भी दशमलव संख्याओं के रूप में प्रदर्शित होते हैं।

<<0b1011::4>> == <<11::4>>
# => true

काटना

अगर सेगमेंट की वैल्यू उस सेगमेंट के टाइप की क्षमता से बढ़ जाए, तो उसे बाईं ओर से काट दिया जाता है।

<<0b1011::3>> == <<0b0011::3>>
# => true

आगे और पीछे जोड़ना

आप स्पेशल फॉर्म की मदद से किसी मौजूदा बिटस्ट्रिंग के आगे और पीछे दोनों तरफ जोड़ सकते हैं। अगर मौजूदा बिटस्ट्रिंग का साइज़ पता न हो, तो उस पर ::bitstring टाइप इस्तेमाल करना ज़रूरी है।

value = <<0b110::3, 0b001::3>>
new_value = <<0b011::3, value::bitstring, 0b000::3>>
# => <<120, 8::size(4)>>

एक साथ जोड़ना

वेरिएबलो में रखी बिटस्ट्रिंग को हम स्पेशल फॉर्म की मदद से एक साथ जोड़ सकते हैं। जब दो बिटस्ट्रिंग का साइज़ पता न हो, तो जोड़ते समय ::bitstring टाइप इस्तेमाल करना ज़रूरी है।

first = <<0b110::3>>
second = <<0b001::3>>
concatenated = <<first::bitstring, second::bitstring>>
# => <<49::size(6)>>

पैटर्न मैचिंग

स्पेशल फॉर्म से वैल्यू निकालने के लिए पैटर्न मैचिंग भी की जा सकती है। हर उस टुकड़े के लिए बिट की संख्या पता होनी चाहिए जिसे आप कैप्चर करना चाहते हैं। इसका एक अपवाद है: ::bitstring टाइप की मदद से किसी अनजान साइज़ की बिटस्ट्रिंग पर भी पैटर्न मैचिंग की जा सकती है, लेकिन यह सिर्फ अंतिम टुकड़े के लिए ही काम करती है।

<<value::4, rest::bitstring>> = <<0b01101001::8>>
value == 0b0110
# => true

बिटस्ट्रिंग को देखना

Note

बिटस्ट्रिंग कभी-कभी उस फॉर्मेट से अलग फॉर्मेट में प्रिंट हो सकती हैं जिस फॉर्मेट में उन्हें बनाया गया था (टेस्ट रनर द्वारा या iex में)। बिटस्ट्रिंग सीखते समय इससे अक्सर उलझन होती है।

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

<<2011::11>>
# => <<251, 3::size(3)>>

अगर आप ऐसी बिटस्ट्रिंग बनाते हैं जो किसी प्रिंट करने योग्य UTF-8 एनकोडेड स्ट्रिंग को दर्शाती है, तो वह स्ट्रिंग के रूप में प्रदर्शित होती है।

<<>>
# => ""

<<65, 66, 67>>
# => "ABC"

निर्देश

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

आपको Elixir में एक ऐसा ऐप बनाने का काम दिया गया है, जिसमें नंबर के हिसाब से रंग भरे जाते हैं। आप चाहते हैं कि आपका ऐप चित्रों को एक अपने खास डेटा फॉर्मेट में इम्पोर्ट और एक्सपोर्ट कर सके। आपने अपने चित्रों का डेटा रखने के लिए बाइनरी फाइलों का उपयोग करने का फैसला किया है।

Note

इस अभ्यास में यह मान लिया गया है कि आप बाइनरी संख्याओं से परिचित हैं और यह समझते हैं कि बाइनरी संख्याओं को दशमलव संख्याओं में और दशमलव संख्याओं को बाइनरी संख्याओं में बदलने के पीछे क्या सिद्धांत काम करते हैं।

मान लीजिए कि आपके पास एक स्माइली का चित्र है, जैसा नीचे दिखाया गया है। चित्र की पृष्ठभूमि सफेद है। स्माइली का किनारा काला है और उसके अंदर पीला रंग भरा है।

इस चित्र में 3 रंग इस्तेमाल होते हैं। मान लीजिए हम इन रंगों को इंडेक्स देते हैं:

  • 0 (बाइनरी: 0b00) सफेद के लिए,
  • 1 (बाइनरी: 0b01) काले के लिए,
  • 2 (बाइनरी: 0b10) पीले के लिए।

अब हम इन रंग इंडेक्सों से हर पिक्सल का रंग दर्शा सकते हैं।

स्माइली रंग इंडेक्स वाली स्माइली

1. पैलेट का बिट साइज़ निकालिए

PaintByNumber.palette_bit_size/1 फंक्शन लागू कीजिए। यह पैलेट में रंगों की संख्या लेता है और लौटाता है कि उतने रंग इंडेक्सों को बाइनरी संख्याओं के रूप में दर्शाने के लिए कितने बिट ज़रूरी हैं। रंग इंडेक्स हमेशा 0 से शुरू होते हैं और लगातार बढ़ते पूर्णांक होते हैं।

उदाहरण के लिए, 13 अलग-अलग रंगों को दर्शाने के लिए 4 बिट चाहिए। 4 बिट में 16 तक रंग इंडेक्स रखे जा सकते हैं (2^4)। 3 बिट काफी नहीं होंगे, क्योंकि 3 बिट में 8 तक ही रंग इंडेक्स रखे जा सकते हैं (2^3)।

PaintByNumber.palette_bit_size(13)
# => 4

नोट: Elixir की स्टैंडर्ड लाइब्रेरी में log2 फंक्शन नहीं होता। आगे आप सीखेंगे कि Elixir से Erlang लाइब्रेरी कैसे इस्तेमाल की जाती हैं, जहाँ आपको यह फंक्शन मिल जाएगा। अभी इस काम को रिकर्शन और पावर ऑपरेटर ** की मदद से हल कीजिए।

2. खाली चित्र बनाइए

PaintByNumber.empty_picture/0 फंक्शन लागू कीजिए। यह एक खाली बिटस्ट्रिंग लौटाता है।

3. टेस्ट चित्र बनाइए

आपके ऐप के बुनियादी फीचरों को हाथ से जाँचने के लिए एक पहले से तय टेस्ट चित्र इस्तेमाल किया जाएगा। इस टेस्ट चित्र में 4 पिक्सल हैं, जिनके 4 अलग-अलग रंग हैं।

PaintByNumber.test_picture/0 फंक्शन लागू कीजिए। यह एक ऐसी बिटस्ट्रिंग लौटाता है जिसमें 4 सेगमेंट होते हैं। हर सेगमेंट का बिट साइज़ 2 होना चाहिए। इन सेगमेंट की वैल्यू 0, 1, 2 और 3 होनी चाहिए।

4. चित्र के आगे एक पिक्सल जोड़िए

PaintByNumber.prepend_pixel/3 फंक्शन लागू कीजिए। यह तीन आर्गुमेंट लेता है: वह चित्र जिसके आगे हम पिक्सल जोड़ रहे हैं (बिटस्ट्रिंग के रूप में), पैलेट में रंगों की संख्या, और नए पिक्सल के रंग का इंडेक्स। यह एक ऐसी बिटस्ट्रिंग लौटाता है जिसमें नया पिक्सल चित्र के शुरू में जुड़ा होता है।

picture = <<2::4, 0::4>>
color_count = 13
pixel_color_index = 11

PaintByNumber.prepend_pixel(picture, color_count, pixel_color_index)
# => <<178, 0::size(4)>>
# (which is equal to <<11::4, 2::4, 0::4>>)

5. चित्र से पहला पिक्सल निकालिए

PaintByNumber.get_first_pixel/2 फंक्शन लागू कीजिए। यह दो आर्गुमेंट लेता है: वह चित्र जिसे हम पढ़ रहे हैं (बिटस्ट्रिंग के रूप में), और पैलेट में रंगों की संख्या। यह दिए गए चित्र के पहले पिक्सल का रंग इंडेक्स लौटाता है। जब खाली चित्र दिया जाए, तो यह nil लौटाता है।

picture = <<19::5, 2::5, 18::5>>
color_count = 20

PaintByNumber.get_first_pixel(picture, color_count)
# => 19

6. चित्र से पहला पिक्सल हटाइए

PaintByNumber.drop_first_pixel/2 फंक्शन लागू कीजिए। यह दो आर्गुमेंट लेता है: वह चित्र जिससे हम एक पिक्सल हटा रहे हैं (बिटस्ट्रिंग के रूप में), और पैलेट में रंगों की संख्या। यह पहले पिक्सल के बिना वाला चित्र लौटाता है। जब खाली चित्र दिया जाए, तो यह एक खाली चित्र लौटाता है।

picture = <<2::3, 5::3, 5::3, 0::3>>
color_count = 6

PaintByNumber.drop_first_pixel(picture, color_count)
# => <<180, 0::size(1)>>
# (which is equal to <<5::3, 5::3, 0::3>>)

7. दो चित्रों को जोड़िए

PaintByNumber.concat_pictures/2 फंक्शन लागू कीजिए। यह दो आर्गुमेंट लेता है, दोनों बिटस्ट्रिंग। यह एक ऐसी बिटस्ट्रिंग लौटाता है जो पहले आर्गुमेंट को दूसरे आर्गुमेंट के आगे जोड़ने पर बनती है।

picture1 = <<52::6, 51::6>>
picture2 = <<0::6, 34::6, 12::6>>

PaintByNumber.concat_pictures(picture1, picture2)
# => <<211, 48, 34, 12::size(6)>>
# (which is equal to <<52::6, 51::6, 0::6, 34::6, 12::6>>)
GitHub के ज़रिए संपादित करें यह लिंक एक नई विंडो या टैब में खुलता है
Elixir Exercism

नंबर से रंग भरिए शुरू करने के लिए तैयार हैं?

Exercism पर साइन अप कीजिए और Elixir को 58 कॉन्सेप्ट168 अभ्यास तथा असली इंसानों से मिलने वाली मेंटरिंग के साथ सीखिए और उसमें महारत हासिल कीजिए, वह भी बिल्कुल मुफ्त।