ট্র্যাক
/
JavaScript
JavaScript
/
অনুশীলনী
/
পিৎজা অর্ডার
পিৎজা অর্ডার

পিৎজা অর্ডার

লার্নিং অনুশীলনী

ভূমিকা

রিকার্সন প্রোগ্রামিংয়ের একটি শক্তিশালী ধারণা, যেখানে একটি ফাংশন নিজেকেই কল করে। শুরুতে এটি বুঝতে একটু কঠিন লাগতে পারে, কিন্তু মূল বিষয়গুলো একবার বুঝে গেলে জটিল সমস্যা সমাধানে এটি একটি দরকারি হাতিয়ার হয়ে ওঠে। এই টিউটোরিয়ালে আমরা সহজে বোঝা যায় এমন উদাহরণের মাধ্যমে জাভাস্ক্রিপ্টে রিকার্সন দেখব।

রিকার্সন কী?

কোনো ফাংশন যখন সরাসরি বা পরোক্ষভাবে নিজেকেই কল করে, তখন তাকে রিকার্সন বলে। এটি লুপের মতোই, তবে এতে একটি সমস্যাকে ছোট ছোট, সহজে সামলানো যায় এমন উপ-সমস্যায় ভাগ করা হয়।

উদাহরণ ১: কাউন্টডাউন

চলুন একটি সহজ উদাহরণ দিয়ে শুরু করি: একটি কাউন্টডাউন ফাংশন।

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 দিয়ে নিজেকে কল করে।

উদাহরণ ২: ফ্যাক্টোরিয়াল

এবার চলুন রিকার্সনের একটি ক্লাসিক উদাহরণ দেখি: একটি সংখ্যার ফ্যাক্টোরিয়াল নির্ণয়।

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-এর ফ্যাক্টোরিয়াল দিয়ে গুণ করে।

মূল ধারণাগুলো

বেস কেস

প্রতিটি রিকার্সিভ ফাংশনে অন্তত একটি বেস কেস থাকতে হবে, অর্থাৎ এমন একটি শর্ত যেখানে ফাংশনটি নিজেকে কল করা বন্ধ করে। বেস কেস না থাকলে রিকার্সনটি অনির্দিষ্টকাল ধরে চলতেই থাকবে, যার ফলে স্ট্যাক ওভারফ্লো হতে পারে।

রিকার্সিভ কেস

রিকার্সিভ কেস ঠিক করে দেয় কীভাবে ফাংশনটি সমস্যার আরও ছোট বা সরল একটি সংস্করণ দিয়ে নিজেকে কল করবে।

রিকার্সনের সুবিধা ও অসুবিধা

সুবিধা:

  • নির্দিষ্ট কিছু সমস্যার জন্য সুন্দর সমাধান।
  • গাণিতিক আরোহ পদ্ধতির ধারণার মতো কাজ করে।

অসুবিধা:

  • ইটারেটিভ সমাধানের চেয়ে কম দক্ষ হতে পারে।
  • গভীর রিকার্সনে স্ট্যাক ওভারফ্লো হতে পারে।

উপসংহার

রিকার্সন একটি মূল্যবান কৌশল, যা জটিল সমস্যাকে ছোট ছোট, সহজে সামলানো যায় এমন উপ-সমস্যায় ভেঙে দিয়ে সহজ করে তুলতে পারে। জাভাস্ক্রিপ্টে কার্যকর রিকার্সিভ সমাধান করতে বেস কেস আর রিকার্সিভ কেস বোঝা খুবই জরুরি।

আরও জানুন:

নির্দেশনা

আপনি একটি পিৎজার দোকান চালান, এবং তিন ধরনের পিৎজা বিক্রি করেন:

  • 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টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।