Thursday, November 16, 2017

তোমরা যারা নতুন প্রোগ্রামিং শুরু করছো...

প্রোগ্রামিং কন্টেস্ট এর নাম শুনলেই অনেকে জিজ্ঞেস করে ভাইয়া কোন ল্যাংগুয়েজ দিয়ে করতে হবে? অনেকে আবার বলে ভাইয়া এই প্রব্লেম টা সল্ভ করতে কি কি ব্যবহার করতে হবে? আমিতো অ্যারে পারিনা! অ্যারে ছাড়া চলবে? অনেকে আবার প্রোগ্রামিং কে গতানুগতিক সাব্জেক্টের সাথে মিলিয়ে ফেলে বা পরীক্ষার আগে সাজেশনও খোঁজে। এইটা দেখে আমার ফিলিংস - OMK( ও মোর খোদা ) টাইপ! 😋
এসবের তিনটা কারন হতে পারে  এক- সে প্রোগ্রামিং কন্টেস্ট সম্পর্কে জানেনা, দুই-  সে প্রোগ্রামিং কি সেটা জানেনা, তিন- ত্রুটিপুর্ণ বাংলাদেশী শিক্ষাব্যবস্থার সাথে দীর্ঘ দিনের অভ্যস্ততা । এই ব্যপারগুলো থেকে একটা জিনিস স্পষ্ট যে প্রোগ্রামিং দর্শনটা তার কাছে পরিষ্কার করা জরুরি। নাহলে সারাদিন প্রোগ্রামিং প্রোগ্রামিং আর হ্যাপি কোডিং বলে চিল্লানী দিলেও কোন ধরনের লাভ হবেনা। দীর্ঘ দিনের পর্যবেক্ষন অভিজ্ঞতা থেকেই আজকের লেখা-


                                                                           এক 

তোমরা কি কখনো খেয়াল করেছো, যেকোন সমস্যা সমাধান করার সময় তিনটা জিনিস সবসময় আমাদের করতে হয়? বিশ্বাস হচ্ছেনা? একটু নিজে নিজে চিন্তা করে দেখোঃ

১। ইনপুটঃ ইনপুট হল ডাটা সংগ্রহ করা। আমাকে যদি কোন সমস্যা সমাধান করতে বলা হয় তার জন্য আমার প্রয়োজনীয় জিনিসপত্রের দরকার হবে। এই জিনিসপত্র সংগ্রহ করার নামই হল ইনপুট।

২। অপারেশনঃ এই ধাপটা হল সমস্যা সমাধানের ধাপ। ইতোমধ্যে ডাটাগুলো আমার হাতে আছে। এখন সেই ডাটাগুলো ব্যাবহার করে আমি পার্টিকুলার সমস্যাটি সমাধান করবো।

৩। আউটপুটঃ এই অংশটা হল সমাধানটা দেখানোর জন্য। অপারেশন চালিয়ে আমি যে সমাধানটা বের করলাম সেই সমাধানটা দেখানোর জন্যই এই ধাপ। আর কিছু না।

                                                                         দুই

মনে করো আমি তোমার দুই হাতে দুইটা করে মার্বেল দিয়ে বললাম মার্বেল গুলো আমাকে যোগ করে দেখাও। তুমি কি করবে? দুই হাতের মার্বেল গুলো একটা পাত্রে রেখে তুমি আমাকে দিয়ে দিলে। আমি ঐ পাত্রের মার্বেলগুলো গুনে দেখলাম সেখানে ৪টা মার্বেল। বলতো এখানে তুমি কি কাজ করেছো?

ধাপ- ১ঃ হাত বাড়িয়েছো
ধাপ- ২ঃ মার্বেল হাতে নিয়েছো  //ইনপুট
ধাপ- ৩ঃ দুই হাতের মার্বেল একত্র করে পাত্রে রেখেছো।   //অপারেশন
ধাপ- ৪ঃ আমাকে সেই পাত্রটা দিয়ে দিয়েছো। //আউটপুট

১ থেকে ৩ পর্যন্ত কাজটা তোমাকে করতেই হবে। কারন তোমার হাতে ডাটাগুলো হাতে না নিলে তুমি অপারেশন করতে পারবানা। সেজন্যই তোমাকে ১ থেকে ৩ পর্যন্ত কাজগুলো করতেই হবে। এখন যেহেতু তোমার হাতে ডাটা রেডি; অপারেশনের কাজটা এখন করতে হবে। সেই অপারেশনটার নাম হচ্ছে যোগ করা। এখন যোগ কিভাবে করতে হয়? সেটা তোমাকে ছোটবেলায় কোন এক স্কুলে শিখিয়ে দেওয়া হয়েছে যে, দু বা ততোধিক সংখ্যাকে একত্র করলে তাকে যোগ বলে। আর সেজন্যই তুমি দুই হাতের মার্বেল একত্র করে পাত্রটা আমাকে দিয়ে দিয়েছো। যে কাজটা তুমি এখন করলে,  সাধারন ভাষায় এটা মানুষ করলে বলা হয় ম্যাথমেটিক্স আর কম্পিউটার দিয়ে করলে বলা হয় প্রোগ্রামিং।

এখন কথা হল তোমাকে আমি যে মার্বেল দিয়ে বললাম আমাকে এটা যোগ করে দাও। এই কথাটা আমি তোমাকে বাংলায় বললাম। আমি চাইলে এই কথাটা ইংলিশে বা অন্য কোন ল্যাংগুয়েজে বলতে পারতাম তাইনা?

কিন্তু কম্পিউটার যেহেতু বাংলা বা ইংরেজি বুঝেনা সেজন্য তার জন্য আলাদা ল্যাঙ্গুয়েজ তৈরী করা হয়েছে। যে ল্যাঙ্গুয়েজটা কম্পিউটার বুঝে এমনকি মানুষও বুঝে। সেরকমই কিছু প্রোগ্রামিং ল্যাংগুয়েজের নাম-  C, C++, Java, Python, Rubi, Pascal সহ আরো অনেক।

এখন উপরের কাজটি যদি আমি কম্পিউটারের মাধ্যমে করতে চাই তাহলে আমাকে এদের যেকোন একটি ল্যাঙ্গুয়েজ ব্যাবহার করতে হবে। তাহলে C প্রোগ্রামিং ল্যাঙ্গুয়েজ দিয়ে উপরের কাজটি সমাধান করে ফেলি।

 // Example program  
 #include <stdio.h>  
 int main()  
 {  
  int left_hand, right_hand; //hat barano :P   
  scanf("%d%d", &left_hand, &right_hand); //hate marvel newa :P   
  int bottle = left_hand+right_hand; //marvel gulare jog kore bottle a rakha   
  printf("%d", bottle); //output dewa ba dekhano   
 }  


                                                                       তিন
অনেকে বলে ভাইয়া, আমিতো অ্যারে পারিনা ওমুক প্রব্লেমটা অ্যারে ছাড়া করা যাবে? বা এই প্রব্লেমটা করতে If else ব্যাবহার করতে হবে?
আসলে প্রোগ্রামিং ল্যাঙ্গুয়েজে ভেরিয়েবল, অ্যারে, লুপ, ফাংশন, স্ট্রিং এগুলো প্রোগ্রামিং ল্যাঙ্গুয়েজের কয়েকটা ফিচার। তোমার যখন দরকার হয় তখন তুমি এটা ব্যাবহার করবে। শুধু তোমাকে জেনে রাখতে হবে কোনটা কিভাবে লিখে এবং কেন ব্যাবহার করতে হবে। যেকোন সময় যেকোনটা ব্যবহার করার দরকার হতে পারে। এজন্য কোন অবস্থাতেই কোনটাকে বাদ দেওয়া যাবেনা। নিজের প্রয়োজনেই শিখে রাখতে হবে। তোমাকেই বুঝতে হবে কোথায় কি ব্যাবহার করতে হবে। যেমন ধর, আমি যদি উপরের প্রব্লেমটাতে বলে দিতাম  শুধুমাত্র মার্বেল সংখ্যা দুইটা বা তার বড় হয় তবেই যোগ করবে। এসব পরিস্থিতিতে তোমাকে if else করতে হবে। যেমন আগের প্রোগ্রামটি সামান্য আপডেট করলেই হয়ে যাবে -

 // Example program   
  #include <stdio.h>   
  int main()   
  {   
  int left_hand, right_hand; //hat barano :P    
  scanf("%d%d", &left_hand, &right_hand); //hate marvel newa :P    
  if(left_hand>=2 && right_hand>=2>){  
    int bottle = left_hand+right_hand; //marvel gulare jog kore bottle a rakha    
    printf("%d", bottle); //output dewa ba dekhano    
    }  
  else  
   printf("Do Nothing");  
  }   

আবার যদি তোমাকে ৫০টা মারবেল যোগ করতে দিতাম তখন কি করতে? তখন কি তুমি ৫০ বার হাত বাড়াতে? কিম্বা ৫০ টা ভেরিয়েবল ডিক্লেয়ার করতে? কখনোই না। তুমি যেহেতু স্মার্ট সিমপ্লি অ্যারের সাহায্য নিবে কারন তুমি জানো অ্যারে দিয়ে মুহূর্তের মধ্যে অনেকগুলো ভেরিয়েবল ডিক্লেয়ার করা যায়। আবার তোমার যদি একই কাজ বার বার করতে হয় তাহলে তুমি নিশ্চয়ই লুপ ইউজ করবে। আশাকরি এই ব্যাপারটা এখন ক্লিয়ার।


                                                                       চার

তোমরা কি এতক্ষনে কিছু বুঝতে পেরেছো প্রোগ্রামিং ল্যাংগুয়েজের সীমাবদ্ধটা আসলে কোথায়!  প্রোগ্রামিং ল্যাঙ্গুয়েজ হল লিমিটেড। অথ্যাৎ, নির্দিষ্ট একটা সময় শেষে তুমি এই ল্যাঙ্গুয়েজটা আয়ত্ব করতে পারবা এবং দিনশেষে এটা সমস্যা সমাধানের একটা অস্ত্র ছাড়া কিছুই না। অস্ত্র হিসেবে তুমি যেকোন একটা প্রোগ্রামিং ল্যাঙ্গুয়েজ ব্যাবহার করতে পারবা। কিন্তু অস্ত্র থাকলেই তুমি যুদ্ধের ময়দানে জিতে যাবা? কখনোই না। যদি তাই হতো, তাহলে যুদ্ধক্ষেত্রে কোন সেনা নিহত হতোনা।

শুধু হাতে অস্ত্র থাকলেই হয়না সেজন্য দরকার সেই অস্ত্র চালানোর প্রয়োজনীয় টেকনিক বা কৌশল। তাহলে সে কৌশল বা টেকনিকটা আসলে কি? উপরের উদাহরনে দুই হাতের মার্বেল পাত্রে রেখে দেওয়াই হল একটা কৌশল। তুমি চাইলে সেটা অন্যভাবেও করতে পারতে। বাম হাতের মার্বেলগুলো ডান হাতে এনে তুমি আমাকে ডান হাতটা দেখিয়ে দিতে পারতে। অথবা উল্টোটাও করতে পারতে।যেটা তোমার করতে সুবিধে হয় বা দ্রুত করা যাবে তুমি নিশ্চয়ই সে পদ্ধতিটা অনুসরন করবে।  এখন তুমি যদি না জানতে দুইটা জিনিসকে একত্র করাকে যোগ বলে তাহলে তুমি কি প্রোগ্রামিং ল্যাঙ্গুয়েজ জানা সত্ত্বেও করতে পারতে? কখনোই না।

এমন অনেক প্রবলেম আছে যা সাধারনভাবে করা যায়না। এজন্য নতুন নতুন টেকনিক বের করতে হয়। টেকনিক বের করার জন্য প্রচুর চিন্তা করতে হবে এবং লেগে থাকতে হবে। টেকনিকটাকে কম্পিউটার সায়েন্সের এর ভাষায় এলগরিদমও বলা হয়।

প্রোগ্রামিং কন্টেস্টগুলোতে তোমাকে ওরকম এক সেট প্রব্লেম দিয়ে দেওয়া হবে যা তোমাকে যেকোন প্রোগ্রামিং ল্যাঙ্গুয়েজ দিয়ে সল্ভ করতে হবে। প্রোগ্রামিং প্রব্লেমগুলো সর্বোচ্চ ইজি থেকে শুরু করে সর্বোচ্চ কঠিন পর্যন্ত হতে পারে। এজন্য তোমাকে জানতে হবে প্রচুর টেকনিক, প্রচুর অ্যালগিরদম এবং অবশ্যই করতে হবে প্রচুর প্র্যক্টিস। এর কারন হল, এখানে তোমাকে যোগ করতে বলা হয়েছে আর যেহেতু তুমি যোগ সেই বাচ্চাকালে শিখে আসছো তাই করতে সমস্যা হয়নি। কিন্তু এমন হাজার হাজার প্রব্লেম তোমাকে ফেস করতে হবে যা অতীতে তুমি সমাধান করোনি বা চিন্তাও করোনি। এজন্য তোমাকে শিখতে হবে নতুন নতুন টেকনিক বের করতে হবে নতুন নতুন অ্যালগোরিদম।


                                                                    পাঁচ

টেকনিক নিয়ে তো অনেক অনেক কথা হল। এবার দেখি টেকনিকটা আসলে কিভাবে সমস্যা সমাধানে ভেরিয়েশন আনে।

আমরা জানি, যে সংখ্যাকে ঐ নাম্বারকে ১ এবং ঐ নাম্বার ছাড়া অন্য কোন নাম্বার দিয়ে ভাগ করা যায়না তাকে প্রাইম নাম্বার বলে। মনে করো তোমাকে আমি বললাম, কোন নাম্বার প্রাইম কি প্রাইম না তার চেক করার একটা প্রোগ্রাম আমাকে লিখে দাও। সেক্ষেত্রে তোমার কৌশল কি হতে পারে?

কৌশল - ১ঃ যেহেতু তোমার কাজ হল প্রাইম নাম্বার চেক করা আর আমরা জানি প্রাইম নাম্বার ১ এবং ঐ সংখ্যা ছাড়া বাকী নাম্বার দিয়ে ভাগ যায়না। তার মানে বলা যায় যেসব সংখ্যার মাত্র দুইটা ডিভাইজর বা ভাজক তাকেই প্রাইম নাম্বার বলে। তাহলে পরীক্ষা করে দেখি। মনে করে সংখ্যাটা ৬।

 6/1 = 6  
 6/2 = 3  
 6/3 = 2  
 6/4 = Not evenly Divisable  
 6/5 = Not evenly Divisable   
 6/6 = 1  
যেহেতু ৬ এর দুইটার বেশী ডিভাইজর (১, ২, ৩, ৬) পাওয়া গেল তাহলে ৬ প্রাইম নাম্বার না।

আবার ৭ এর জন্য করে দেখিঃ
 7/1 = 7  
 7/2 = Not evenly Divisible   
 7/3 = Not evenly Divisible   
 7/4 = Not evenly Divisalbe   
 7/5 = Not evenly Divisable  
 7/6 = Not evenly Divisable   
 7/7 = 1  

যেহেতু ৭ এর মাত্র ২ টা ডিভাইজর তার মানে ৭ হল প্রাইম নাম্বার।

এতক্ষন তো হাতে হাতে করলাম।  এখন এই কাজটা প্রোগ্রামিং দিয়ে কিভাবে করবে?  উপরে খেয়াল করলে দেখবা আমি ১ থেকে শুরু করে N পর্যন্ত সংখ্যা দিয়ে ভাগ করলাম এবং গননা করলাম মোট কতবার নিঃশেষে কতবার ভাগ গেলো। যদি সেই সংখ্যাটা দুই হয় তাহলে প্রাইম আর তা নাহলে প্রাইম না। যদি তুমি প্রোগ্রামিং ল্যাঙ্গুয়েজ জানো তাহলে এই কথাটাই সি দিয়ে ঝটপট লিখে ফেলো।

 // Example program  
 #include <stdio.h>  
 int main()  
 {  
   int N, count = 0;  
   scanf("%d", &N);  //input 
   for(i = 1;i<N;i++){  //operation
     if(N%i == 0)  
       count++;  
     }  
   if(count == 2)  
     printf("Prime\n");  //output
   else  
     printf("Not Prime");  
  return 0;  
 }  

এই টেকনিকটা প্রাইম নাম্বার বের করার সবচেয়ে বাজে টেকনিক। কারন অনেক বড় মানের জন্য এটি রেজাল্ট দিতে বছর লেগে যাবে। বিশ্বাস হচ্ছেনা? কম্পিউটার একটা সমস্যা সল্ভ করতে বছর লাগিয়ে দিবে!! সিরিয়াসলি!! বিশ্বাস না নীচের অংশটুকু তোমার জন্য-

আমরা এখানে N বার ভাগ করেছি। যদি N এর মান 1000000000000 হতো তাহলে 1000000000000 বার ভাগ করতে হতো। কম্পিউটারে একবার ভাগ করতে যদি ১ মিলি সেকেন্ড লাগে, তাহলে 1000000000000 টা ভাগ  করতে 1000000000000 মিলি সেকেন্ড লাগবে যা 1000000000 সেকেন্ড বা 16666666 মিনিট বা 277777 ঘন্টা বা 11574 দিন! বিশ্বাস না হলে রান করে দেখো। তোমার আউটপুট আসতে ১১৫৭৪ দিন লেগে যাবে! কিন্তু এই সময়টা সেকেন্ডে নিয়ে আনা যায়। সেজন্য তোমাকে চিন্তা করে অপটিমাইজ করতে হবে।

এইটা অপটিমাইজ করতে হলে তোমাকে ভাগ সংখ্যা কমিয়ে আনতে হবে। সেটা কিভাবে করতে হবে তার জন্য নতুন কৌশল বের করো। চিন্তার যায়গাটা আসলে এখানেই। এইটা তোমার হোমওয়ার্ক রইলো। আশাকরি, বিষয়গুলো বুঝতে কোন সমস্যা হয়নি। পরবর্তীতে প্রাইম নাম্বার বের করার আরো কিছু অপটিমাইজড ট্রিক্স নিয়ে আলোচনা হবে।

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

2 comments: