Saturday, June 28, 2014

ভিজ্যুয়াল প্রোগ্রামিং

Visual শব্দটির অর্থ চাক্ষুষ বা সরাসরি দৃশ্যমান। Programming এর ভাষায় Visual মানে কোড না লিখে প্রোগ্রামের বিভিন্ন User Interface সমূহ প্রোগ্রামে সংযুক্ত করা। এক্ষেত্রে User Interface সমূহে সংযোজনের কাজ অনেকটা চিত্র আঁকার মতই। সুতরাং ভিজ্যুয়াল প্রোগ্রামিং একটি চিত্রভিত্তিক প্রোগ্রামিং মডেল যা Windows Operating System কর্তৃক সমর্থিত। মেনুচালিত প্রোগ্রাম রচনার ক্ষেত্রে এ মডেলটি খুবই উপযোগী।
মূলত ভিজ্যুয়াল প্রোগ্রামিং হচ্ছে এমন এক ধরনের উইন্ডোজ ভিত্তি Object Oriented Programming যাতে মেনু, চিত্র, বিভিন্ন ধরনের টুল বা কন্ট্রোল ব্যবহার করে বাস্তব ভিত্তিক যে কোন সমস্যা অতি সহজে সমাধান করা যায়।

বহুল প্রচলিত ভিজ্যুয়াল সফটওয়্যার সমূহঃ


  • ভিজ্যুয়াল বেসিক
  • ভিজ্যুয়াল ফক্সপ্রো
  • ভিজ্যুয়াল সি
  • ভিজ্যুয়াল সি++
  • ভিজ্যুয়াল জাভা
  • পাওয়ার বিল্ডার
  • ডেভেলপার ২০০০ ইত্যাদি।

ভিজ্যুয়াল প্রোগ্রামিং এর বৈশিষ্ট্যসমূহ


  • ভিজ্যুয়াল প্রোগ্রামিং এর ক্ষেত্রে ভিজ্যুয়াল ডেভেলপমেন্ট এনভায়রনমেন্ট ব্যবহার করে নতুন কোন এপ্লিকেশন ডেভেলপ করার পুরো প্রক্রিয়াটিই ভিজ্যুয়াল এবং গ্রাফিক্স প্রকৃতির।
  • ভিজ্যুয়াল প্রোগ্রামিং এর বেলায় GUI (Graphical User Interface) অপারেটিং সিস্টেম যেমন উইন্ডোজ ব্যবহৃত হয়।
  • Command এর পরিবর্তে Menu, Tools বা Control ব্যবহার করে সমস্যার সমাধান করা যায়। User গণ Command মুখস্থ না করে মাউসের মাধ্যমে ক্লিক করে যে কোন কার্য সম্পন্ন করতে পারে।
  • প্রয়োজনীয় যথেষ্ট সংখ্যক লাইব্রেরি ফাংশন, সাবরুটিন, কাস্টম লাইব্রেরি ও কাস্টম অবজেক্ট তৈরির সুবিধা বিদ্যমান থাকায় স্বল্প সময়ে প্রোগ্রাম রচনা করা যায়।
  • এডিটিং এর বেলায় কোড এর পরিবর্তে শক্তিশালী কন্ট্রোল ব্যবহার করে মাউস ক্লিক এর মাধ্যমে নিজের ইচ্ছামত ডিজাইন করে ফলাফল পাওয়া যায়।
  • ভিজ্যুয়াল প্রোগ্রামিং এর অসাধারণ ডিবাগিং পদ্ধতি বিদ্যমান। ফলে সহজে ও অল্প সময়ে প্রোগ্রামের ভুল-ত্রুটি সনাক্তকরণ ও সংশোধন করা যায়।
  • সর্বোপরি ভিজ্যুয়াল প্রোগ্রামিং এ ব্যবহৃত অবজেক্টসমূহ বাস্তব জীবনের সাথে সম্পর্কিত বিধায় এটি ইউজার ফ্রেন্ডলি।

ভিজ্যুয়াল প্রোগ্রামিং এর ব্যবহারিক ক্ষেত্রসমূহ


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

ভিজ্যুয়াল প্রোগ্রামিং এর প্রয়োজনীয়তা


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

সবাইকে অসংখ্য ধন্যাবাদ ।।।। ভালো থাকবেন ।।।।
……… {সমাপ্ত}………

স্ট্যান্ডার্ড টেম্প্লেট লাইব্রেরী

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


দ্বিতীয় অংশ – স্ট্যান্ডার্ড টেম্প্লেট লাইব্রেরী

STL হল একটা বেশ বড়সড় একটা লাইব্রেরী। মোটামুটি বেশিরভাগ ডাটা স্ট্রাকচার আর হাবিজাবি এটার মধ্যে লিখে রাখা আছে, তোমাকে শুধু জানতে হবে সেটা তুমি কিভাবে ব্যবহার করবে।
 

 ভেক্টর

মাঝে মাঝে এমন হয় – আমাদের একটা 2D অ্যারে দরকার, যেটায় মোটামুটি প্রতিটায় সর্বোচ্চ ১০০০০ টা ডাটা রাখতে হবে, আর প্রতিটা ডাটায় সর্বোচ্চ ১০০০০টা করে ডাটা রাখা লাগবে। কিন্তু আমাকে এটাও বলা আছে যে সর্বোচ্চ ১০০০০০ টা ডাটা থাকতে পারে। 

খুব সাধারণভাবে যেটা মাথায় আসে, সেটা হচ্ছে এরকম কিছু একটা 
 int array[10000][10000];

তাই না? এটা কিন্তু বেশ বড়সড় একটা অ্যারে। আমার কম্পিউটার মাথা ঘুরে পড়ে যাবে তাকে এই পরিমান মেমরি অ্যালোকেট করতে বললে, কিন্তু আমার আসলে এত বেশি জায়গা লাগছে না, কারণ আমাকে বলেই দেয়া হয়েয়ে ডাটা সবমিলে সর্বোচ্চ ১০০০০০ টা থাকে পারে। 

এধরণের সময়, আমরা ডাইনামিক মেমরি অ্যালোকেট করি – ঠিক যতটুকু মেমরি দরকার ঠিক ততটুকুই নেই। যেটা ম্যানুয়ালি করা বেশ ঝক্কি, আর সেটায় মেমরি পরিষ্কারও করে দিতে হয় কাজ শেষে, নইলে সব ডাটা জমতে জমতে কম্পিউটারের গলা চিপে ধরে।

ভেক্টর হলো একটা অ্যারে, যেটায় ডাইনামিকালি জিনিসপাতি ঢুকিয়ে রাখা যায়। মানে, এটাও একটা অ্যারে, কিন্তু সেটা ঠিক ততটুকু মেমরি খায়, যতটুকু খাওয়া লাগে।

ভেক্টর ডিক্লেয়ার করে এভাবে

vector< int > array;

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

vector< double > water;
vector< long long > balance;
vector< char > characters;
vector< day > diary;

ভেক্টরে কোন ডাটা রাখতে হলে, সেই ভেক্টরের শেষে ডাটাটাকে পুশ করতে হয়।

array.push_back( 100 );


 আর ভেক্টরে কটা ডাটা আছে সেটা আমরা জানতে পারি .size() ফাংশনকে কল করে। যেমন ধরো, আমি একটা ভেক্টরে কিছু ইন্টেজার ঢুকাবো, তারপর সবাইকে প্রিন্ট করবো, সেটার কোড হবে এরকম।


int main() {
    vector< int > v;
    v.push_back( 1 ); 
    v.push_back( 2 ); 
    v.push_back( 3 ); 
    v.push_back( 4 );     for(int i=0; i<v.size(); i++) cout << v[i] << endl;
    
    return 0;   
}

বাকি সব কিছুতে ভেক্টরকে সাধারণ অ্যারের মত ব্যবহার করা যায়। যেমন আমি 0th এলিমেন্টটা পাল্টে দিতে পারি v[0] = 10000 লিখে। আরেকটা মজা হচ্ছে আমরা অ্যারেতে ধাম করে সরাসরি কপি করতে পারি না । কিন্তু ভেক্টরে সেটা করা যায়। 
 

int main() {    vector< int > v, t;    v.push_back( 1 );    v.push_back( 2 );    v.push_back( 3 );    v.push_back( 4 );    t = v; // copying    for(int i=0; i<t.size(); i++) cout << t[i] << endl;
    return 0;

ভেক্টরে যদি আমি 2D ডাটা রাখতে চাই তাহলে সেটা দুভাবে করা যায়। আমি প্রথমটা প্রেফার করি, পরেরটা দেখতে আমার ভয় ভয় লাগে। কিন্তু মাঝে মাঝে কোন পথ থাকে না সেটা লেখা ছাড়া।

vector< int > v[100];
vector< vector< int > > v;
vector< vector< vector< int > > > v; // 3 dimensional

একটা জিনিসে একটা সাবধান থেকো, vector<vector<int>> v; এভাবে লিখলে >> এর জন্য কিছু কম্পাইলর কিন্তু এরর মারে।


স্ট্রিং

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


int main() {    string a, b, c;    a = “this is a string”; // easy assigning    b = a; // copy hoye gelo! :O    c = a + b // c te rakhlam a ar b er concatation    cout << c << endl; // print korlam    printf(“%s\n”, c.c_str() ); // printf diyei korlam na hoy
    cout << c.size() << endl; // length print korlam    for(int i=0; i<c.size(); i++) cout << c[i] ; 
// ekta ekta kore character print korlam
return 0;
}

তুমি যদি এখন স্ট্রিং এর ভেক্টর রাখতে চাও তাহলে সেটাকে ডিক্লেয়ার করতে হবে এভাবে।

vector< string > vs;

সহজ না?

স্ট্যাক

ধরো, তোমার মা একগাদা প্লেট ধুতে নিয়ে যাচ্ছে খাওয়ার টেবিল থেকে। সবার পরে যেটা রাখা হবে, সেই প্লেটটাকে কিন্তু সবার উপরে রাখা হবে, আর সেটাই কিন্তু সবার আগে ধোয়া হবে।

এই জিনিসটাকে বলে স্ট্যাক। মানে আমরা সবার পরে যাকে প্রসেসিং করতে ঢুকাচ্ছি তাকে যদি আগে প্রসেসিং করি তাহলে সেটাই স্ট্যাক। STL এ স্ট্যাক ব্যবহার করতে হয় এভাবে।

 stack< int > st;
st.push( 100 ); // inserting 100
st.push( 101 ); // inserting 101
st.push( 102 ); // inserting 102

while( !st.empty() ) {
cout << st.top() << endl; // printing the top
st.pop(); // removing that one
}

কিউ

ধরো তুমি বাসের টিকেট কিনে লাইনে দাঁড়িয়ে আছো। এখন বাসে ওঠাটা হচ্ছে আমার কাজ(প্রসেসিং)। কাকে আগে বাসে উঠতে দিবে? যে সবার আগে এসেছে, তাকে। এটাকে বলে কিউ – যে সবার আগে এসেছে তাকে আগে প্রসেস করা। 
 


queue< int > q;
q.push( 100 ); // inserting 100
q.push( 101 ); // inserting 101
q.push( 102 ); // inserting 102

while( !q.empty() ) {
cout << q.front() << endl; // printing the front
q.pop(); // removing that one
}
 

প্রায়োরিটি কিউ

আমাদের পাড়ার মুচির প্রতিদিন একগাদা কাজ আসে। সে করে কি, সবচে’ বেশি পয়সা পাওয়া যাবে যেই কাজে সেই কাজগুলো সবার আগে করে ফেলে। সে প্রায়োরিটি তাদেরকেই বেশি দেয় যাদের কাজে বেশি পয়সা পাওয়া যাবে। 

এটাও এক ধরণের কিউ শুধু পার্থক্য হচ্ছে যার দাম যত বেশি তাকে তত আগে প্রসেস করা হচ্ছে।

priority_queue< int > q;
q.push( 10230 ); // inserting 10230
q.push( 1021 ); // inserting 1021
q.push( 102322 ); // inserting 102322

while( !q.empty() ) {
cout << q.top() << endl; // printing the top
q.pop(); // removing that one
}


ইটারেটর

ইটারেটার হলো  অনেকটা সি এর পয়েন্টারের মত একটা জিনিস। ইটারেটর আসলে পরে কাজে লাগবে, কারণ অনেক জায়গায়ই STL এর ফাংশনগুলো একটা অ্যাডরেস পাঠায়, যে আমি যেই ডাটাটাকে খুঁজছি, সেটা ঠিক কোথায় আছে।

ইটারেটর ডিক্লেয়ার করে এইভাবে

vector< int > :: iterator i;
vector< double > :: iterator j;


আর ফর লুপ দিয়ে একটা ভেক্টরের প্রথম থেকে শেষ পর্যন্ত সব এলিমেন্টের গলা কাটতে চাই তাহলে সেটা লিখতে হবে এভাবে।

vector< int > v; v.pb( 1 ); v.pb( 2 ); v.pb( 3 );
vector< int > :: iterator i;
for( i = v.begin(); i < v.end(); i++ ) {
printf(“%d\n”, *i);
// ei khane gola kato!
}

 
সর্ট

ধরো আমার কাছে কিছু নাম্বার আছে, আমি সেগুলোকে ছোট থেকে বড়তে সাজাবো, বা উল্টো কাজটা করবো, বড় থেকে ছোটতে সাজাবো। এই কাজটাকে বলে সর্ট করা। যদি তুমি সর্ট করার নিয়ে পড়াশুনা করে ফাটাই ফেলতে চাও তাইলে  এইখানে একটু ঢু মারো।

STL এ সর্ট করা খুব সহজ। ধরো আমার একটা ভেক্টর v আছে, সেটা আমি সর্ট করবো। তাহলো আমার শুধু লিখতে হবে -

sort( v.begin(), v.end() );
তাহলে সে ছোট থেকে বড় তে ভেক্টরটাকে সর্ট করে ফেলবে। এখন ধরো আমাকে যদি আরেকটু ঝামেলার কিছু করতে বলে। যেমন ধরো চাচা চৌধুরী তার মেয়ের বিয়ে দিবে, তো সে গেলো ঘটক পাখি ভাইয়ের কাছে। ঘটক পাখি ভাইয়ের কাছে একটা ছেলে মানে, তার নাম-ধাম, তার বংশ, সে কত টাকা কামায়, তার উচ্চতা কতো, আর তার ওজন কত। ছেলেটা সি++ এ কোড করে না জাভাতে কোড করে, সেটা নিয়ে ঘটক পাখি ভাইয়ের কোনই মাথা ব্যাথা নাই। তো সে করলো কি চাচা চৌধুরীকে শুধু এই ক্য়টা ডাটাই সাপ্লাই দিলো কয়েকটা বস্তা ভরে। এখন চাচা চৌধুরী পাড়ার প্যান্ট ঢিলা মাস্তানের কাছ থেকে শুনলো তুমি একটা বস প্রোগ্রামার, তো সে এসে তোমাকে বলল, “বাবাজি! আমাকে একটা সফটওয়্যার বানিয়ে দাও, যেটা আমার ডাটাগুলোকে সাজাবে”।

বেশ তো, এখন আমার ডাটাটা হচ্ছে এরকম – (চাচা চৌধুরী আবার বংশ নিয়ে মাথা ঘামায় না)

struct data {
    char name[100];
    int height, weight;
    long long income;
};

চাচা চৌধুরী যেটা নিয়ে মাথা ঘামায় সেটা হলো পোলার কত টাকা কামাই। যদি দুইটা পোলার সমান কামাই হয়, তাইলে যেই পোলার হাইট ভালো, সেই পোলা লিস্টে আগে থাকবে। আর যদি দুই পোলার হাইট সমান হয় তাইলে যেই পোলার ওজন কম, সেই পোলা আগে থাকবে। আর যদি দুই পোলার ওজন সমান হয়, তাইলে যেই পোলার নাম ছোট সেই পোলা আগে থাকবে।

এখন তোমাকে এই অনুযায়ী সর্ট করে দিতে হবে। আর তুমি যদি বেশি হাংকি পাংকি করো, তাইলে প্যান্ট ঢিলা মাস্তান এসে তোমাকে সাইজ করে দিবে।

এই কাজটা দুই ভাবে করা যায়। সবচে সহজটা হলো একটা কম্পেয়ার ফাংশন লিখে।

bool compare( data a, data b ) {
    if( a.income == b.income ) {
        if( a.height == b.height ) {
            if( a.weight == b.weight ) 
              return strlen( a.name ) < strlen( b.name );
else return a.weight < b.weight;
}else return a.height > b.height;
}else return a.income > b.income;
}


এই ফাংশনটা গ্লোবালি ডিক্লেয়ার করে যেখানে তুমি সর্ট করতে চাও সেখানে লিখতে হবে।
sort( v.begin(), v.end(), compare );

কম্পেয়ার ফাংশনটা রিটার্ন করবে a কি b এর আগে বসবে কি না। আর কিছু না।

সর্ট করার অন্য পথটা হচ্ছে অপারেটর ওভারলোড করে। ধরো, আমরা যখন বলি ২ < ৩ আমরা বুঝে নেই যে ২ হচ্ছে ৩ এর ছোট – মানের দিক দিয়ে। এখন একটা স্ট্রাকচার কখন অন্য আরেকটা স্ট্রাকচারের চেয়ে ছোট হবে? এই জিনিসটা তোমার প্রোগ্রামে ডিফাইন করে দিতে হবে। এখানে খেয়াল করো, ছোট হবার মানে বোঝাচ্ছে সে লিস্টে আগে থাকবে।

আমি যদি একই কাজটা অপারেটর ওভারলোড দিয়ে করতে চাই, সেটা এরকম হবে।

struct data {
char name[100];
int height, weight;
long long income;

bool operator < ( const data& b ) const {
if( income == b.income ) {
if( height == b.height ) {
if( weight == b.weight )
                   return strlen( name ) < strlen( b.name );
                else return weight < b.weight;
            }else return height > b.height;
        }else return income > b.income;
    }};

এখানে কিন্তু আমি এই ডাটাটাকেই অন্য আরেকটা ডাটা b এর সাথে তুলনা করছি, সেজন্য আমার আগেরটার মতো a কে লাগছে না।

আর আমার সর্ট এর কমান্ড লিখতে হচ্ছে এইভাবে।
     sort( v.begin(), v.end() );

তোমার যদি ভেক্টর ব্যবহার করতে আপত্তি থাকে, ধরো ভেক্টর দেখলেই হাঁচি আসা শুরু করে, নাক চুলকায় কিংবা এধরণের কিছু, তুমি সাধারণ অ্যারেই ব্যবহার করতে পারো।
ধরো সেক্ষেত্রে অ্যারেটা হবে এরকম -

data array[100];
sort( array, array + n );

যেখানে n হচ্ছে অ্যারেতে কতগুলো ডাটাকে তুমি সর্ট করতে চাও।

তুমি যদি 3 নাম্বার (0 based)থেকে 10 নাম্বার পর্যন্ত সর্ট করতে চাও লিখো
 sort( array+3, array+11 );

 

সেট 

কোন কিছুর সেট বলতে আসলে বুঝায় শুধু জিনিসগুলোর নাম একবার করে থাকাকে। 
যেমন A = { রহিম, করিম, গরু, বিড়াল, করিম, বালিশ, রহিম, করিম } একটা সেট না, কিন্তু
 A = { রহিম, করিম, গরু, বিড়াল, বালিশ } একটা সেট।

STL এর সেট করে কি, সেট এ সব ডাটা গুলো একবার করে রাখে, আর ডাটাগুলোকে সর্ট ও করে রাখে। এটা হলো সেট এর কাজ কারবার - 


    set< int > s;
s.insert( 10 ); s.insert( 5 ); s.insert( 9 );

set< int > :: iterator it;
for(it = s.begin(); it != s.end(); it++) {
cout << *it << endl;
}
যদি তুমি স্ট্রাকচার টাইপের ডাটা রাখতে চাও সেট এ, শুধু < অপারেটরটা ওভারলোড করে ওকে বলে নিও, যে তুমি ছোট বলতে কি বুঝাচ্ছো।  বাকি কাজ ওই করবে। 

সেট সাধারণত এধরণের প্রবলেমগুলোতে কাজে লাগে। আমাকে অনেকগুলো সংখ্যা দিয়ে বলল, এখানে ইউনিক কয়টা সংখ্যা আছে। সেক্ষেত্রে আমি খালি একটার পর একটা সংখ্যা ইনপুট নিতে থাকবো তো নিতেই থাকবো, আর সেটে ঢুকাবো তো ঢুকাতেই থাকবো, তারপর খালি সেটের সাইজ প্রিন্ট করে দিবো। কেল্লা ফতেহ!

ম্যাপ

ম্যাপও সেটের মতো একটা জিনিস। কিন্তু ম্যাপ সেটের মত কোন জিনিস একটা রেখে ওই ধরণের বাকি সবাইকে বাইরে ফেলে দেয় না। 

তবে এভাবে ভাবার চেয়ে ম্যাপকে আরেকটু সহজভাবে ভাবা যায়। একটা অ্যারের কথা চিন্তা করো, আমরা করি কি অ্যারের একটা ইনডেক্সে ডাটা জমাই না? কেমন হতো, যদি ইনডেক্সটা শুধু সংখ্যা না হয়ে যেকোন কিছু হতে পারতো? ধরো, ১ নম্বর ইনডেক্সে না রেখে, “বাংলাদেশ” নামের ইনডেক্সে ডাটা যদি রাখতে পারতাম? তখন ব্যাপারটা দাঁড়াতো আমাদের একটা ম্যাজিক অ্যারে আছে যেটাই আমরা যেকোন ধরণের ডাটা জমিয়ে রাখতে পারি আমাদের ইচ্ছা মতো যে কোন ধরণের ইনডেক্স দিয়ে।

সহজভাবে ম্যাপকে তুমি এভাবে চিন্তা করতে পারো, ম্যাপ হচ্ছে একটা অ্যারে, যেটার ইনডেক্স যেকোন কিছুই হতে পারে, আর সেটাতে যেটা ইচ্ছে সেটাই রাখা যেতে পারে!

map< string, int  > m;
string goru;

while( cin >> goru ) {
if( goru == “moro” ) break;
m[ goru ] ++;
cout << goru <<” ase ” << m[ goru ] << ” ta :D ” << endl;
}
এই প্রোগ্রামটা করবে কি, গরুর নাম ইনপুট নিতে থাকবে, আর প্রতিবার বলবে যে ওই জাতের কয়টা গরু আছে।  ম্যাপকে অ্যারের মত ধরেই ইনক্রিমেন্ট করা যায়।

অবশ্য তুমি যদি তোমার বানানো কোন স্ট্রাকচার/ক্লাস রাখতে চাও ইনডেক্স হিসেবে, তোমাকে সেটার জন্য < অপারেটরটা ওভারলোড করে দিতে হবে।

 স্ট্রিংস্ট্রিম

 ধরো কোন শয়তান খুব শখ করে প্রবলেম সেট তৈরী করলো, আমাকে বলল, “তোমাকে একলাইনে যত্তগুলা ইচ্ছা তত্তগুলা করে সংখ্যা দিমু, তুমি আমারে সর্ট কইরা দিবা! মুহাহাহাহা!” তখন কষে একটা চড় মারতে ইচ্ছে করলেও কিছু করার নেই। তোমাকে তাই করতে হবে। 

আমরা লাইনের ইনপুট নেই হচ্ছে গেটস দিয়ে।
তো ব্যাপারটা এরকম হবে। 

char line[1000];
while( gets( line ) ) {
stringstream ss( line ); // initialize kortesi
int num; vector< int > v;
while( ss >> num ) v.push_back( num ); // :P
sort( v.begin(), v.end() );
// print routine
}


ss এর পরের হোয়াইল লুপ অংশটা তুমি cin এর মতো করেই ভাবতে পারো! ;) আমি সেভাবেই চিন্তা করি।
 

পেয়ার

STL এর একটা স্ট্রাকচার বানানো আছে, যার অবস্থা মোটামুটি এইরকম।

struct pair {
    int first, second;
};

তবে জিনিসটা এমন না, তুমি যেকোন টাইপে কাজ করতে পারো। যেমন এটা যদি আমি STL এর পেয়ার দিয়ে লিখি, জিনিসটা হবে এরকম 

pair< int, int > p; 


এই চেহারাটা কি মনে পড়ে? একে কি আগে দেখেছো? হুমম, ম্যাপের স্ট্রাকচারে আরেকবার চোখ বুলাও। ;)

আমরা ইচ্ছে মতো পেয়ার ডিফাইন করতে পারি, যেভাবে ইচ্ছে। ম্যাপের ডাটা টাইপের মতনই!

pair< int, int > p;
pair< int, double > x;
pair< double, string > moru;
pair< goru, goru > fau;

যা ইচ্ছে!
 

নেক্সট পারমুটেশন, প্রিভ পারমুটেশন

 ধরো হঠাৎ একদিন ঘুম থেকে উঠে দেখলা যে তোমার এগারোটা বাচ্চা এবং কালকে ঈদ আর আজকে তোমার ওদের জন্য ঈদের জামা কিনতে হবে। সমস্যা হচ্ছে, তোমার বউ এরই মধ্যে এগারোটা জামা কিনে ফেলেছে আর আরো সমস্যা হচ্ছে সেটা সে লটারি করে দিয়ে দিয়েছে এবং সেজন্য যাদের যাদের জামা পছন্দ হয়নি তারা কান্নাকাটি করছে। তো তোমার খুব মন খারাপ, তুমি চাও ঈদের দিনের সুখ যাতে সবচে’ বেশি হয়। আর তুমি এটাও জানো কোন জামা পড়লে কোন বাচ্চা কতটুকু সুখি হবে। এখন আমাদের সবার সুখের যোগফল ম্যাক্সিমাইজ করতে হবে। 

এধরণের প্রবলেমকে বলা হয় কম্প্লিট সার্চ। আমাদের সবগুলো অপশন ট্রাই করতে হবে। ধরো তিনটা বাচ্চার জন্য অল পসিবল ট্রাই করা হচ্ছে এরকম – (জামার নাম্বার দিয়ে)

আবু গাবু ডাবু
  ১     ২    ৩
  ১     ৩    ২
  ২     ১    ৩
  ২     ৩    ১
  ৩     ১    ২
  ৩     ২    ১
  
এখন এভাবে যদি আমি এগারোটা বাচ্চার জন্য ঈদের জামা পড়িয়ে দেখতে চাই আমার খবরই আছে – 11! ভাবে ট্রাই করতে হবে। তো সেই জন্যই আছে STL এর নেক্সট পারমুটেশন

    vector< int > v;
for(int i=0; i<11; i++) v.push_back( i );

do {
// protitat jama prottekke porai dekho shukh maximize hochche kina
}while( next_permutation( v.begin(), v.end() ) );
 
আমরা ৩ এর জন্য যেভাবে সবগুলো পারমুটেশন জেনারেট করেছি, সেটাই এই নেক্সট পারমুটেশন করবে। খেয়াল কোর যে, নেক্সট পারমুটেশন কিন্তু ঠিক অ্যালফাবেটিকালি পরের পারমুটেশনটাকে নেয়। তুমি যদি সব পারমুটেশন চাও, প্রথমে অবশ্যই অ্যারেটাকে সর্টেড রেখো।

 রিভার্স

রিভার্স হচ্ছে একটা কিছুকে ধরে উল্টাই দেয়া।
ধরো আমার একটা ভেক্টর আছে।
 

vector< int > nacho;
reverse( nacho.begin(), nacho.end() );

পরের স্টেটমেন্টটা লিখলে, সে নাচোকে উল্টাই দিবে।

তো এই ছিলো ব্যাসিক সি++ আর STL।

C++ STL :: pair

কিছু কথাঃ

যারাই কিনা সি/সি++ নিয়ে বেশকিছুদিন নাড়াচাড়া করছেন, তারা প্রায় সবাই সি এর একটা দারুন জিনিস স্ট্রাকচার-এর সাথে পরিচিত, আর, আরেকটু অ্যাডভান্সডরা তো মনে হয় অলরেডি সি++ এর ক্লাস নামের জিনিসটা মোয়া বানিয়ে ফেলেছে।
সি একটা ফাটাফাটি ল্যাঙ্গুয়েজ আর সি++ এর কথা তো বলাই বাহুল্য। যারা অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিং এর সুবাতাস পেয়েছেন তারা এটা আরো ভাল করে জানেন। আমরা জানি, সি++ এ কিছু প্রিমিটিভ ডাটা টাইপ ডিফাইন করা আছে, যাদের উপরে আমরা খুব সহজেই বিভিন্ন অপারেশন চালাতে পারি, কিন্তু মাঝে মাঝে এই রকমের ডাটা টাইপের ব্যবহার আমাদের কে ঝামেলায় ফেলতে পারে। যেমন, মনে করা যাক আমাকে একটা 2D গ্রিডের কিছু পয়েন্ট স্টোর করতে হবে। শুধু int টাইপের অ্যারে দিয়ে এটা মেইনটেইন করাটা বেশ মুশকিলের ব্যাপার। কিন্তু যদি এরকম একটা ডাটা টাইপ থাকতো ‘point’ নামে, যা কিনা (x, y) আকারে কো-অর্ডিনেট রাখতে পারতো!!! সি এ সেই ব্যাবস্থা করেই দেয়া আছে, যেন প্রোগ্রামাররা চাইলেই ইচ্ছা মতো ডাটা টাইপ বানিয়ে নিতে পারেন, আর সি++ এটাকে আরেক ডিগ্রি এগিয়ে নিয়ে গেছে। এখানে প্রোগ্রামার চাইলে তার বানানো ডাটা টাইপের আচার আচরণও বলে দিতে পারেন।
কিন্তু, প্রশ্ন হল, এটা কন্টেস্ট প্রোগ্রামিং এর জন্য কতটা সুইটেবল?

পেয়ার কি?

কন্টেস্ট প্রোগ্রামিং-এ সাধারনতঃ খুব কমপ্লেক্স ডাটা টাইপ বানাতে হয় না। সেখানে বেশি প্রয়োজন খুব দ্রুত আর নির্ভুল কোডিং। যেমন, প্রায়ই দেখা যায়, একটা গ্রাফের এজ গুলো স্টোর করতে হবে, বা জিয়োমেট্রির প্রবলেমের জন্য কো-অর্ডিনেট নিয়ে কাজ করতে হবে, কখনো বা দেখা যায় কিছু স্ট্রিং-এর জন্য কিছু নাম্বার দিতে হবে, অথবা একগাদা ডাটা বিভিন্ন ক্রাইটেরিয়ার ভিত্তিতে সর্ট বা সার্চ করতে হবে। সাধরনতঃ এসব ক্ষেত্রে প্রোগ্রামার যদি নিজে থেকে ডাটাটাইপ বানাতে যায়, কোন সন্দেহ নাই তাতে তার মূল্যবান কিছু সময় নষ্ট হবে। যেমন, নিচের প্রবলেমটা দেখিঃ
আমাকে একগাদা 2D পয়েন্ট থাকবে, আমাকে সেগুলা সর্ট করতে হবে। এখন, আমি চাইলেই একটা স্ট্রাকচার বানাতে পারিঃ

structpoint { int x, y; } P[128];
অর্থাৎ, P[] হল একটা পয়েন্ট টাইপের অ্যারে, এখন এটাকে সর্ট করতে হবে। কাজ তো সোজাই, অ্যালগোরিদমের হেডারটা ইনক্লুড করে sort() মেরে দিলেই হয়… কিন্তু আসলে এটা এত সিম্পল না, কারন, sort() একটা টেমপ্লেট ফাংশন, মানে যে কোন ডাটাটাইপের জন্য কাজ করবে, কিন্তু তার আগে তাকে ডাটাটাইপের ভাবগতি জানাতে হবে। আমি ‘struct point’ দিয়ে কি বুঝাতে চাই, এটা তার বুঝার কোন কারনই নাই যদি না আমি বলে দেই। তার মানে খালি sort() কে ডাকলেই চলবে না, তার সাথে অপারেটর ওভারলোড বা কম্পেয়ার ফাংশন লিখে বুঝিয়ে দিতে হবে যে আমি আসলে কি চাই। আর এখানেই std::pair এর প্লাস পয়েন্ট।
std::pair জিনিশটা তেমন কিছুই না, জাস্ট দুইটা ভ্যালু কে একসাথে করে রাখে, যেখানে ভ্যালু দুইটা যে কোন টাইপের হতে পারে, ডিফারেন্ট টাইপেরও হতে পারে। পেয়ার ক্লাসটা ডিফাইন করা থাকে std <utility> নামের হেডারে।
#include <utility>
using namespace std;
pair ক্লাসের ডেফিনিশনঃ
template <class T1, class T2> struct pair {
    T1 first;
    T2 second;
    pair(): first(T1()), second(T2()) {}
    pair(const T1 &x, const T2 &y): first(x), second(y) {}
    template <class U, class V> pair(const pair<U, V> &p): first(p.first), second(p.second) {}
};
যাদের টেমপ্লেট সম্পর্কে আইডিয়া নাই, তাদের জন্য অল্প কথায়, টেমপ্লেট একটা সিস্টেম যেখানে কোন অ্যাকচুয়াল টাইপের জন্য ডিজাইন থাকে না, বরং যে কোন টাইপের জন্য তার একটা ইন্সট্যান্স তৈরি করা যায়। টেমপ্লেট শিখতে হলেএই পেজটি দেখা যেতে পারে।
pair এর সুবিধা হল, এটা টেমপ্লেট টাইপ, তাই STL algorithm এর ফাংশন গুলার জন্য সাধারনতঃ pair অবজেক্ট গুলার আলাদা করে কোন পরিচয় দেওয়ার দরকার পড়ে না। যেমন আগের প্রবলেমে জাস্ট sort() কল দিলেই চলে, সে অটমেটিক প্রথমে পেয়ারের প্রথম মেম্বার, তার পর ২য় টা, তার পর ৩য় টা, এভাবে বাকি গুলা কম্পেয়ার করে দেখবে। প্রোগ্রামারকে এর জন্য কিছুই বলতে হবে না।

কিভাবে ব্যবহার করে?

pair নিয়ে কাজ করতে চাইলে <utility> হেডার ইনক্লুড করা উচিৎ, অবশ্য যে কোন STL হেডার ইনক্লুড করলেই pair ব্যবহারের সুবিধা পাওয়া যায়। আর pair টাইপের অবজেক্ট সহজে ক্রিয়েট করার জন্য <utility> হেডারের make_pair() ফাংশন ব্যবহার করা যায়। আর pair-এর ১ম আর ২য় এলিমেন্টকে যথাক্রমে .first আর .second মেম্বার দিয়ে অ্যাক্সেস করা যায়। নিচে একটা উদাহরন দেখানো হলঃ
#include <iostream>
#include <string>
#include <utility>
using namespace std;
int main() {
    // simple constructions
    pair< int, int > px, py;
    pair< int, int > p1(23, 43);
    pair< int, int > p2 = pair< int, int >(234, 534);
    px = p1;
    py.first = p2.first * px.second, py.second = p2.second * px.first;
    cout << "py: (" << py.first << ", " << py.second << ")\n";
    
    // bit more complex
    pair< pair< int, int >, pair< int, int > > p3;
    p3 = pair< pair<int, int>, pair< int, int > > (px, py);
    cout << "p3: ((";
    cout << p3.first.first << ", " << p3.first.second << "), (";
    cout << p3.second.first << ", " << p3.second.second << "))\n";
    
    // using make_pair()
    pair< double, pair< string, int > > p4;
    p4 = make_pair(3.14159, make_pair("pi", 5) );
    cout << "this is " << p4.second.first << ", value: " << p4.first;
    cout << " precision: " << p4.second.second << " digits\n";
    return 0;
}
pair নিয়ে সবচেয়ে বেশি যে কথাটা শোনা যায় তা হল, মানুষজন নাকি .first.second.second.first…. এরকম চেইন লিখতে লিখতে টায়ার্ড হয়ে যায়। কিন্তু একটু কাজ করেই এইটাকে সহজ করে ফেলা যায়, যেমন, নিচের কোডে pair কে #define করে নেওয়া হয়েছেঃ
#include <iostream>
using namespace std;
#define pii pair< int, int >
#define ppi pair< pii, int >
#define ff first
#define ss second
int main() {
    ppi p1;
    pii p2;
    cin >> p2.ff >> p2.ss;
    p1 = ppi( p2, p2.ss * p2.ff );
    cout << "entry: " << p1.ff.ff << ", " << p1.ff.ss << endl;
    cout << "product: " << p1.ss << endl;
    return 0;
}
অন্যান্য STL কন্টেইনারের ডাটা টাইপ হিসাবেও pair ব্যবহার করা যায়। যেমন, বি.এফ.এস. অ্যালগরিদমে প্রায়ই কিউতে একজোড়া নাম্বার রাখতে হতে পারে, অথবা ডায়াকস্ট্রার অ্যালগরিদমে পুরা একটা এজকে প্রাইওরিটি কিউতে রাখার ব্যাবস্থা করতে হয়। এটাও খুব সহজেই করা যায়ঃ
#include <queue>
using namespace std;
#define pii pair< int, int >
#define edge pair< int, pii >
// edge.first is weight, edge.second is a pair indicating endpoints
queue< pii > Q;
priority_queue< edge, vector< edge >, greater< edge > > PQ;

সতর্কতাঃ

অন্যান্য সব STL অবজেক্টের মত, এখানেও একটা ব্যাপার খেয়াল করতে হবে তা হলঃ উপরের উদাহরন গুলাতে দেখা যায় কন্সট্রাকশন শেষ করার সময় মাঝে মাঝে পর পর দুইটা > ব্যবহার করতে হয়, (যেমন প্রাইওরিটি কিউ এর উদাহরনে শেষে ……greater< edge > >, এখানে শেষ ২টা > এর মাঝখানে একটা স্পেস ব্যবহার করা হয়েছে, এটা কিন্তু সৌন্দর্য বর্ধনের জন্য না। এটা না দিলে অনেক সময় কম্পাইলারের মাথা গরম হয়ে যায়। কারন সি++ এ >> আরো কয়েকটা অপারেটরের কাজ করে। আর যেসব যায়গায় দেখা যায় pair ইউজ করলে আরো ঝামেলা হয়, সেখানে নরমাল স্ট্রাকচার ব্যবহার করাটাই বেশি ভাল। এটা জেনে রাখা ভাল, আর জানলেই যে বসাতে হবে এমনও কোন কথা নাই।

ব্যবহারঃ

সাধারনতঃ STL এর টেমপ্লেট ক্লাসগুলোর ওভারলোডিং সুবিধা নেওয়ার জন্য এবং ছোটো খাটো স্ট্রাকচারের শর্টহ্যান্ড হিসাবে pair ব্যবহার করা হয়ে থাকে। এছাড়া std::map এ হাশিং এর সময় pair ব্যবহার করা হয়। প্রোগ্রামিং প্রবলেমগুলাতে গ্রাফ আর জিওমেট্রিক রিপ্রেজেন্টেশনে pair অনেক ব্যবহার করা হয়।