বৃহস্পতিবার, ৮ মে, ২০১৪

রিকার্শন-১



সি প্রোগ্রামিং এর সব থেকে মজার বিষয় বোধহয় রিকার্শনযখন একটা ফাংশন নিজের নাম ধরে ডাকতে থাকে তখন ফাংশনটিকে বলা হয় রিকার্সিভ ফাংশন এবং প্রক্রিয়াটিকে বলাহয় রিকার্শন
এটা হল মোটামুটি রিকার্শন এর সংজ্ঞাশুধু সংজ্ঞা থেকে রিকার্শনের সৌন্দর্য বুঝা কঠিন
void recursion()
{
  printf(“Hello Recursion\n”);
  recursion ();
}
ওপরের recursion() ফাংশনটি একটি রিকার্সিভ ফাংশনফাংশনটির মধ্যে আবার  সে নিজের নাম ধরে ডাকছে। এই প্রোগ্রামটি চালালে তা কখনই থামবে না। সে Hello Recursion প্রিন্ট করবে এবং আবারও recursion () কে ডাকবে আবারও Hello Recursion প্রিন্ট করবে এবং আবারও recursion () কে ডাকবেএভাবে চলতেই থাকবে। তাহলে উপায়!
আমাদের এমন কিছু করা দরকার যাতে ফাংশনটি একসময় নিজেকে ডাকা ছেড়ে দেয়।
এখানে আমি একটা ছোট্ট ট্রিক্স খাটাবো। 

void recursion()
{
    if(i==5)
        return;
    printf("Hello Recursion\n");
    i++;
    recursion ();
}

শুরুতে i এর মান 0. এরপর একবার করে recursion () কল হচ্ছে আর i এর মান আমরা 1 করে বাড়াচ্ছি। যখন i এর মান 5 হচ্ছে তখন ফাংশনটি return করবে। এখানে return মানে আবার কি? আপাতত ধরে নাও return মানে নিজেকে ডাকা ছেড়ে দেয়াযে কেস এর জন্য রিকার্সিভ ফাংশনটি নিজেকে ডাকা ছেড়ে দেয় তাকে বেসকেস বলে।
এতক্ষণ যা বললাম তা বুঝে থাকলে রিকার্শন বোঝার ৬০% কাজ শেষ
এখন তোমাকে যা করতে হবে সেটা হল একটা কোড লিখতে হবেসমস্যাটা এরকম-
তোমাকে একটা int অ্যারে দেয়া হবে। শুরু থেকে শেষ পর্যন্ত মান গুলো প্রিন্ট করতে হবে রিকার্শন ইউস করে। সহজ........ । 
তুমি হয়ত সমস্যাটা দেখেই ঝটপট এরকম একটা কোড লিখবে-

#include<stdio.h>
int arr[100];
void recursion(int i,int n)
{
    if(i==n)
          return;
    else
        {
          printf("%d ",arr[i]);
          recursion(i+1,n);
       }
}
int main()
{
    int n,i;
    scanf("%d",&n);
    for(i=0; i<n; i++)
        scanf("%d",&arr[i]);
    recursion(0,n);
    return 0;
}

কিন্তু সমস্যা হল আমি এরপর সমস্যাটিকে একটু modify করে তোমাকে বললাম শুরু থেকে শেষ পর্যন্ত নয়, শেষ থেকে শুরু পর্যন্ত প্রিন্ট করতে হবে এবং তোমাকে ফাংশন কল করতে হবে আগের মতই অর্থাৎ recursion(0,n);হবে কলিং স্টেটমেন্ট
প্রথমে নিজে চেষ্টা করনা পারলে কোড দেখ

#include<stdio.h>
int arr[100];
void recursion(int i,int n)
{
    if(i==n)
        return;
    else
    {
        recursion(i+1,n);
        printf("%d ",arr[i]);
    }
}
int main()
{
    int n,i;
    scanf("%d",&n);
    for(i=0; i<n; i++)
        scanf("%d",&arr[i]);
    recursion(0,n);
    return 0;
}

এখানে আসলে কি ঘটেছে দেখ : অ্যারের প্রথম element এর index হচ্ছে 0 আর শেষ element এর index হচ্ছে n-1. যতক্ষণ পর্যন্ত i এর মান n না হচ্ছে ততক্ষন পর্যন্ত i এর মান বাড়াচ্ছি আর recursion(i,n);কল করছিযখনি i এর মান n এর সমান হয়ে গেছে আমরা return করে দিয়েছি। কোন একটা ফাংশন return করা মানে হচ্ছে ফাংশনটিকে যে ফাংশনটি কল করেছে তার কাছে ফিরে যাওয়া
আসলে রিকার্সিভ ফাংশনটি যখন বারবার কল হয় তখন ফাংশনটির একটা করে virtual কপি তৈরি হয়। যেমন প্রথম যখন ফাংশনটি কল হয় সেটি মূল ফাংশন, মূল ফাংশন যখন নিজেকে কল করে তখন তৈরি হয় ১ম কপি, ১ম কপি কল করে ২য় কপিকে, ২য় কপি আবার কল করে ৩য় কপিকে এবং এভাবে চলতে থাকে যতক্ষণ পর্যন্ত না return condition টা ট্রু হয়।
ওপরের solution এ আমরা কি করেছি, যখন i এর মান n এর সমান হয়ে গেছে তখন ফাংশনটি return করেছে তার আগের ফাংশন টার কাছে যার i এর মান ছিল n-1 এবং প্রিন্ট করেছে n-1 index এ থাকা উপাদান, অর্থাৎ শেষ উপাদানটি। এবার এ ফাংশনটিরও কাজ শেষ, সে return করেছে তার আগের ফাংশন এর কাছে যার i এর মান ছিল n-2 এবং প্রিন্ট করেছে n-2 index এ থাকা উপাদানটি। এভাবে যেতে যেতে মূল ফাংশন এ গেলে প্রথম উপাদানটি প্রিন্ট করবে এবং পুরো প্রক্রিয়া সম্পন্ন হবে।
মজার না!!!
এখন তোমাকে একটা মজার সমস্যার সমাধান করতে বলব। এপর্যন্ত বুঝে থাকলে সমস্যাটির সমাধান তোমার কাছে দুধভাতের মত
এমন একটা প্রোগ্রাম লিখতে হবে রিকার্শন ইউস করে যেটা একটা আস্ত স্ট্রিংকে  উল্টায়ে ফেলতে পারে। বুঝতেই পাচ্ছ স্ট্রিং রিভার্স। 
আজ তাহলে উঠি। অনেকক্ষণ বকবক করলাম। আমার এই বকবক করাতে তোমাদের বিন্দুমাত্র উপকার হলে মনে করব আমার পরিশ্রম সার্থক।
হ্যাপি কোডিং!!! :) 



কোন মন্তব্য নেই: