ट्रैक
/
JavaScript
JavaScript
/
अभ्यास
/
पिज़्ज़ा ऑर्डर
पिज़्ज़ा ऑर्डर

पिज़्ज़ा ऑर्डर

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

परिचय

रिकर्शन प्रोग्रामिंग का एक शक्तिशाली कॉन्सेप्ट है, जिसमें एक फंक्शन खुद को कॉल करता है। पहली बार में इसे समझना थोड़ा मुश्किल लग सकता है, लेकिन जब आप इसकी बुनियादी बातें समझ लेते हैं, तो यह जटिल समस्याओं को हल करने का एक बहुत काम का टूल बन जाता है। इस ट्यूटोरियल में हम आसान उदाहरणों की मदद से JavaScript में रिकर्शन को समझेंगे।

रिकर्शन क्या है?

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

उदाहरण 1: उलटी गिनती

चलिए एक आसान उदाहरण से शुरू करते हैं: एक उलटी गिनती वाला फंक्शन।

function countdown(num) {
  // Base case
  if (num <= 0) {
    console.log('Blastoff!');
    return;
  }

  // Recursive case
  console.log(num);
  countdown(num - 1);
}

// Call the function
countdown(5);

इस उदाहरण में:

  • बेस केस: जब num 0 से छोटा या उसके बराबर हो जाता है, तो फंक्शन "Blastoff!" दिखाता है और खुद को कॉल करना बंद कर देता है।
  • रिकर्शन केस: फंक्शन मौजूदा num दिखाता है और खुद को num - 1 के साथ कॉल करता है।

उदाहरण 2: फैक्टोरियल

अब रिकर्शन का एक क्लासिक उदाहरण देखते हैं: किसी संख्या का फैक्टोरियल निकालना।

function factorial(n) {
  // Base case
  if (n === 0 || n === 1) {
    return 1;
  }

  // Recursive case
  return n * factorial(n - 1);
}

// Test the function
console.log(factorial(5)); // Output: 120

इस उदाहरण में:

  • बेस केस: जब n 0 या 1 होता है, तो फंक्शन 1 लौटाता है।
  • रिकर्शन केस: फंक्शन n को n - 1 के फैक्टोरियल से गुणा करता है।

मुख्य कॉन्सेप्ट

बेस केस

हर रिकर्शन वाले फंक्शन में कम से कम एक बेस केस होना चाहिए, यानी ऐसी शर्त जहाँ फंक्शन खुद को कॉल करना बंद कर देता है। बेस केस के बिना रिकर्शन अनंत तक चलता रहेगा, जिससे स्टैक ओवरफ्लो हो जाता है।

रिकर्शन केस

रिकर्शन केस बताता है कि फंक्शन खुद को समस्या के किसी छोटे या आसान रूप के साथ कैसे कॉल करता है।

रिकर्शन के फायदे और नुकसान

फायदे:

  • कुछ खास समस्याओं के लिए बहुत साफ-सुथरा हल।
  • गणितीय आगमन के कॉन्सेप्ट जैसा काम करता है।

नुकसान:

  • इटरेशन वाले हलों की तुलना में कम कुशल हो सकता है।
  • गहरे रिकर्शन में स्टैक ओवरफ्लो हो सकता है।

निष्कर्ष

रिकर्शन एक बहुत काम की तकनीक है, जो जटिल समस्याओं को तोड़कर छोटी और आसानी से संभाली जा सकने वाली उप-समस्याओं में बदल देती है। JavaScript में अच्छे रिकर्शन वाले हल लिखने के लिए बेस केस और रिकर्शन केस को समझना बहुत ज़रूरी है।

और जानिए:

निर्देश

आप एक पिज़्ज़ा की दुकान चलाते हैं और तीन तरह के पिज़्ज़ा बेचते हैं:

  • Margherita: $7
  • Caprese: $9
  • Formaggio: $10

ग्राहक चाहें तो कितने भी अतिरिक्त विकल्प जोड़ सकते हैं: "ExtraSauce" 1 डॉलर में या "ExtraToppings" 2 डॉलर में।

आपको ऐसा कोड लिखना है जो ग्राहक को यह पता लगाने में मदद करे कि उसे कितना देना है।

पिज़्ज़ा की कीमत निकालिए

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

pizzaPrice('Margherita');
// => 7

pizzaPrice('Caprese', 'ExtraSauce', 'ExtraToppings');
// => 12

pizzaPrice(
  'Caprese',
  'ExtraToppings',
  'ExtraToppings',
  'ExtraToppings',
  'ExtraToppings',
);
// => 17

ऑर्डर की कुल कीमत निकालिए

आपके फंक्शन को PizzaOrder के ऐरे के साथ कॉल किया जाता है और उसे ऑर्डर की कुल कीमत डॉलर में लौटानी चाहिए। हर PizzaOrder में एक pizza प्रॉपर्टी होती है, जो पिज़्ज़ा का नाम है, और एक extras प्रॉपर्टी होती है, जो अतिरिक्त विकल्पों का ऐरे है।

const margherita = new PizzaOrder('Margherita');
const caprese = new PizzaOrder('Caprese', 'ExtraToppings');
orderPrice([margherita, caprese]);
// => 18

आप देखेंगे कि इसे रिकर्शन से नहीं लिखा जा सकता, क्योंकि बहुत सारे ऑर्डर वाले एक टेस्ट में Maximum call stack size exceeded एरर आएगी। कोई बात नहीं, यह जानबूझकर है। इस फंक्शन को एक इम्पेरेटिव लूप से लागू करके देखिए! आपके पास कई विकल्प हैं, जैसे reduce या for लूप का उपयोग करना, पर ये ही सब कुछ नहीं हैं।

Advanced

जब JavaScript इंटरप्रेटर JavaScript कोड चला रहा होता है, तो वह यह याद रखता है कि उसने किन-किन फंक्शन में प्रवेश किया है (जिन्हें कॉल करना शुरू किया है)। यह जानकारी वह "स्टैक" नाम की एक डेटा संरचना पर रखता है। जब फंक्शन लौटता है (खत्म होता है), तो उसे स्टैक से हटा दिया जाता है।

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

function kaboom() {
  kaboom()
}

kaboom()
// => RangeError: Maximum call stack size exceeded

इस एरर का स्टैकट्रेस बार-बार वही लाइन दिखाता है, जो समझ में आता है, क्योंकि फंक्शन खुद को ही कॉल करता है। ज़्यादातर मामलों में इसका कोई असली व्यावहारिक उपयोग तो नहीं है, पर आप यह पता लगा सकते हैं कि वह स्टैक कितना ऊँचा हो सकता है।

let calls = 0;
function kaboom() {
  calls +=1 ;
  kaboom()
}

kaboom()
// => RangeError: Maximum call stack size exceeded

console.log(calls)
// => a number, generally higher than 10.000

सिंक्रोनस रिकर्शिव फंक्शन के कारण होने वाली कॉल स्टैक एरर के सिर्फ दो काम के हल हैं:

  • यह सुनिश्चित कीजिए कि फंक्शन स्टैक की सीमा तक पहुँचने से पहले लौट आएँ, आमतौर पर एक बेस केस जोड़कर या ठीक करके।
  • रिकर्शिव फंक्शन को इम्पेरेटिव लूप में बदल दीजिए, जो लूप के अंदर का कोड चलाएगा, बिना किसी फंक्शन में प्रवेश किए, और इस तरह स्टैक को बढ़ाए बिना।
GitHub के ज़रिए संपादित करें यह लिंक एक नई विंडो या टैब में खुलता है
JavaScript Exercism

पिज़्ज़ा ऑर्डर शुरू करने के लिए तैयार हैं?

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