কাজের জায়গায় ভুল থেকে শেখা: regex 'র একটা খুব কমন বিষয় যেটা এতদিন ভুল জানতাম

কাজের জায়গায় ভুল থেকে শেখা: regex 'র একটা খুব কমন বিষয় যেটা এতদিন ভুল জানতাম 
৩ ফেব্রুয়ারি, শনিবার, ২০২৪

রেগুলার এক্সপ্রেশন (Regular Expression or regex) নিয়ে আগেও কিছু কাজ করেছি। টেক্সট ভিত্তিক কিছু প্রবলেম সল্ভ করতে regex খুবই শক্তিশালী একটা টুল। regex -এ ".*" নোটেশন যে any number of character(s) বোঝায় - এটা মোটামুটি সবাই জানে। আমিও জানতাম -- কিন্তু আসলে কথাটা পুরাপুরি সত্যি না, ভুল জানতাম। ভুলটা কী সেইটাই আমার কোডে একটা বাগ ফিক্স করতে গিয়ে শিখলাম,  সঠিক উপায় সম্পর্কে জানলাম। আর তাই আজকের ব্লগ লিখছি। 

[সাইড নোট: tl;dr: মানে যে, too long; didn't read: সেটাও খুব বেশিদিন না, এই কিছুদিন আগে জানলাম। লম্বা পোস্টের মূল বক্তব্য ২-১ লাইনে সারমর্ম আকারে লিখতে ব্যবহার হয়! আমার এই লেখার tl;dr হচ্ছে: regex -এ .* মানে 'any number of single character(s)' - কিন্তু newline (\n) এর আওতায় পড়ে না!] 

কাজের জায়গায় খুব সাধারণ একটা কাজ করতে সেদিন regex ব্যবহার করেছি। প্রবলেমটা ছিল এই রকম: একটা টেম্পলেট  XML ডকুমেন্টে <date> ট্যাগের ভেতর আজকের ডেট বসাতে হবে। তো, আমি ভাবলাম, যেহেতু XML ডকুমেন্টটা string আকারে থাকবে, কাজেই regex'র সাবস্টিটিউট মেথড কল করে <date> .. </date> ট্যাগের ভেতরের যাইই থাকুক, সেটা  .* দিয়ে ক্যাপচার করে আজকের ডেট দিয়ে রিপ্লেস করে দিবো। খুবই সহজ: যেমন নিচের কোড:

ছবি ১: regex দিয়ে আজকের ডেট রিপ্লেস করলাম

কোডটা ব্যাখ্যা করি। লাইন ৪-এ পাইথনে datetime মডিউল দিয়ে now() মেথড কল করে এই মুহূর্তের UTC টাইম নিলাম। স্ট্রিং ফরমেটে  "সাল-মাস-তারিখ ঘন্টা:মিনিট:সেকেন্ড" নেয়ার জন্য strftime() মেথড কল করলাম। (%Y দিয়ে চার ডিজিটের সাল নিলাম) । লাইন ৬ - ৮ -এ XML টেম্পলেট স্ট্রিং ডকুমেন্ট বোঝাতে মাল্টিলাইন স্ট্রিং নিলাম, ধরা যাক, <date> -এ ২০২০ আছে। এরপর ইনপুট স্ট্রিং প্রিন্ট করে, লাইন-১১ তে পাইথনের regex মডিউল (re)'র সাবস্টিটিউট মেথড (sub()) কল করলাম, প্রথম প্যারামিটারে টার্গেট প্যাটার্ন অর্থাৎ "<date>[.* যাই থাকুক]</date>" দিলাম, আর সেটা রিপ্লেস করলাম আজকের তারিখ দিয়ে। লাইন-১২ তে আপডেটেড স্ট্রিং টা প্রিন্ট করিয়ে দেখলাম যে কাজ হয়েছে। আজকের তারিখ দিয়ে ডেট রিপ্লেস হয়েছে। হয়ে গেলো!

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

ছবি ২: ইনপুট স্ট্রিংয়ে নিউলাইন থাকায় regex আর কাজ করে না 

  

 পরে  https://regex101.com/ ওয়েবসাইটে গিয়ে টেস্ট করে দেখি আমার regex প্যাটার্ন আসলেই কাজ করে না, ঐখানেই বাগের হিন্টটা পেলাম যে .* -এ এক্সসেপশন আছে, নিচের ছবিতে: 

ছবি ৩: বাগের হিন্ট 

অর্থাৎ, .* আসলে 'any number of single character(s)' ডিটেক্ট করে, নিউলাইন (\n) ডিটেক্ট করতে পারে না। পরে সলুশনটা StackOverflow'র এই লিংক থেকে পেলাম: .* 'র পরিবর্তে [\s\S]* ব্যবহার করলে সবগুলোই ক্যারেক্টার কভার হয় [\s ='any whitespace character'; \S = 'any non-whitespace character' ]; তখন নিউলাইন (\n) ক্যারেক্টার, যেটা আসলে একটা whitespace character - সেটাও কভার হয়। আর regex -এ স্কোয়ার ব্রাকেট [ ] দিয়ে যেকোনোটা বোঝায়। কাজেই যেকোনো ক্যারেক্টার হলেই সেটা কভার করবে। নিচে বাগ ফিক্স করা কোডটা দিলাম:

ছবি ৪: বাগ ফিক্স করা সঠিক কোড 

সবশেষ: সামান্য এই বাগটা ফিক্স করে ভালো লেগেছে কারণ নতুন একটা জিনিস শিখলাম। আরো ভালো লেগেছে যখন টীম মিটিংয়ে এই বাগটা নিয়ে আলাপ করার পর, সবচেয়ে সিনিয়র ইঞ্জিনিয়ার'ও আমাকে কোনোরকম ভাব না নিয়ে বললো যে সেও আজকে প্রথম ব্যাপারটা জানলো! 

রেপ্লিটে উপরের কোডের লিংক: এই লিংকে  




পাইথনে ইন্টারেষ্টিং বাগ; একই মেথডে ইউনিট টেস্ট সেটআপ আর টিয়ার-ডাউন

পাইথনে ইন্টারেষ্টিং বাগ; একই মেথডে ইউনিট টেস্ট সেটআপ আর টিয়ার-ডাউন
২৯ নভেম্বর ২০২৩, বুধবার 


কাজের জায়গায় রিসেন্টলি একটা ইন্টারেষ্টিং বাগ ফেস করেছি, যেটা আমি নিজেই আসলে না জেনে তৈরী করেছিলাম। পাইথনে শেখা একটা নতুন জিনিস ব্যবহার করতে যেয়েই হয়তো (?) বাগটা কোডে ইন্ট্রোডিউসড হয়েছে। সেটাই প্রথমে লিখছি। তারপর আরেকটা নতুন জিনিস - যেটাও আসলে নতুন শিখলাম - কী করে একটা ইউনিট টেস্টের আগে সেটআপ (test setup) আর টেস্টের পরবর্তী টিয়ার-ডাউন (tear down) একই মেথডে করা যায়, সেটা লিখবো। খুব ছোট করেই লিখবো - কারণ এখন বেশ রাত, ঘুমানো দরকার। 

প্রথম বিষয়: বাগ 
ধরা যাক, নিচের কোডের মতো, আমাদের একটা সিম্পল {string: string } ডিকশেনারী আছে। আমাদের কাজ হচ্ছে, একটা key দেয়া হলে, তার করেস্পন্ডিং value প্রিন্ট করা - খুব সিম্পল ভাবে নিচের মতো করে কোডটা লেখা যায়: 

ছবি: ১

ছবি ১'র লাইন-১০-এর কোড, একটু pythonic করা যায়, যেখানে একলাইনেই কন্ডিশন চেক, আর ভ্যালু এসাইনমেন্ট করা যায়। যেমন নিচের কোডের মতো [এই ব্যাপারটাই আমি নতুন শিখে ভেবেছিলাম ব্যবহার করি!]:

ছবি: ২
val := myDict.get(user_input) আসলে একটা এসাইনমেন্ট স্টেটমেন্ট। প্রথমে ডিকশনারি থেকে ভ্যালু নিয়ে এসে ভ্যারিয়েবল val -এ রাখবে, তারপর if -কন্ডিশন চেক হবে। অর্থাৎ,  ছবি ১ আর ছবি ২ -এর কোড একই আউটপুট দিবে, কোনো সমস্যা নাই। পার্থক্য শুধু হচ্ছে:  ছবি-২'র কোডে ডিকশেনারীটা  দুইবারের বদলে একবার এক্সেস হচ্ছে। ডিকশনারিটা 'get' করে key'র করেস্পন্ডিং value  নিয়ে এসে ভ্যারিয়েবল val -এ রাখছে। যদি key না থাকে, তাহলে ডিফল্ট None ভ্যালু পাবে। আর if None  যেহেতু false তাই, key না থাকলে else ব্লক, অর্থাৎ লাইন ১২-১৩ এক্সেকিউট হবে। কোনো সমস্যা হওয়ার কথা না। তাই না?

কিন্তু এই দুই কোডেই একটা বাগ আছে। কি ধরতে পারছেন? খুব suttle বা সুক্ষ একটা বাগ। একটা হিন্ট দেই, value  যেহেতু string, কোনো একটা key'র রেস্পেক্টিভ value যদি empty string ("") হয়, তখন কি হবে? নিচের কোডে খেয়াল করুন:

ছবি: ৩
আমরা নতুন একটা key-value পেয়ার অ্যাড করেছি (লাইন ৫), যেখানে value আসলে empty string। যখন, key ("empty") দিয়ে ডিকশেনারী লুক-আপ করছি, করেস্পন্ডিং value ("") থাকার পরও বলছে "Key not found"! কারণ কী? কারণটা হচ্ছে, পাইথনে empty string, empty list কিংবা সংখ্যা শূন্য (0) if -কন্ডিশনে false ইভালুয়েট করে বা রিটার্ন করে! আর তাই,  একটা ভ্যালিড value থাকার পরও if কন্ডিশন true রিটার্ন করছে না।

অর্থাৎ, if []: অথবা  if 0:, কিংবা  if "": - সবগুলাই false রিটার্ন করবে 

আশা করি ব্যাগটা বুঝতে পেরেছেন। 

বাগটা সরাতে আমাদের এক্সপ্লিসিটলি বলে দিতে হবে ভ্যারিয়েবল val যেন None না হয়, যেমন নিচের কোডে:



ছবি:৪
ছবি ৪-এ লাইন ১০-এ ভ্যারিয়েবল val -তে ডিকশনারির ভ্যালু রাখার পর এক্সপ্লিসিটলি চেক করছি যে সেটা যেন not None হয়, তবেই প্রিন্ট করছি। এখন empty string ("") যেহেতু None না, তাই if -কন্ডিশন true হবে, আর প্রিন্ট স্টেটমেন্ট এক্সেকিউট হবে, আমরা "Key not found" -এর পরিবর্তে যা চাচ্ছিলাম, সেই এম্পটি স্ট্রিং আউটপুটে দেখতে পাবো [এম্পটি স্ট্রিং হওয়ায় দেখতে আসলে পারছি না :)] 

খেয়াল রাখতে হবে, ব্রাকেট বা পারেনথেসিস না দিলে কিন্তু আরেকটা বাগ তৈরী হবে; কী সেটা? সেটা না হয় নিজেরাই নিচের লিংকে গিয়ে কোড মোডিফাই করে, কোড রান করে দেখে নিন!

কোড: এই লিংকে 

দ্বিতীয় বিষয়: পাইথন ইউনিট টেস্ট: একই মেথডে সেটআপ আর টিয়ার-ডাউন: একটু জটিল 

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

আচ্ছা, যখন আপনার ইউনিট টেস্ট শেষ, এইবার সেটআপ-এ ইন্সার্ট করা ওই এন্ট্রি আপনাকে ডিলিট করতে হবে। এটাই টিয়ার-ডাউন (tear -down) প্রসেস। 

আর এক সেটআপ আর টিয়ার-ডাউন করার দুইটা প্রসেসই একটা মেথড দিয়ে করা যায়! পাইথনে yield কীওয়ার্ড দিয়ে সেটা করা যায়, উদাহরণ হিসাবে নিচের কোডের টেম্পলেট দিচ্ছি:

ছবি: ৫: ইউনিট টেস্ট টেম্পলেট 

পাইথনে @pytest.fixture ডেকরেট ব্যবহার করে আমরা কোনো টেস্ট মেথড রান করার আগে সেটআপ মেথড রান করাতে পারি। ছবি ৫-এ ইউনিট টেস্ট test_method রান করার আগে সবসময় setup_tear_down মেথড কল হবে। 
আর ওই মেথডে প্রথমে ডাটাবেসে এন্ট্রি দিতে হবে। তারপরেই yied কীওয়ার্ড ব্যবহার করে কোডের এক্সেকিউশন caller 'র কাছে ফেরত পাঠানো যায়। Caller অর্থাৎ test_method কাজ শেষ করার পর (টেস্ট মেথড row update count এসার্ট করার পর) আবারো setup_tear_down মেথডে ফেরত আসবে। আর তারপর ডাটাবেস থেকে ওই আপডেটেড এন্ট্রি ডিলিট করে দিলেই আমাদের কাজ শেষ!

আশাকরি  ব্যাপার দুইটা বোঝা গেছে! ধন্যবাদ! 

কাজের জায়গায় যখন আগে শেখা এলগোরিদম, ডাটা স্ট্রাকচার কাজে লাগে!

কাজের জায়গায় যখন আগে শেখা এলগোরিদম, ডাটা স্ট্রাকচার কাজে লাগে!

স্কুলে/কলেজে/ইউনিভার্সিটিতে যেইসব এলগোরিদম আর ডাটা স্ট্রাকচার আমরা শিখি, কিংবা ইন্টারভিউ'র প্রিপারেশন নিতে গিয়ে প্রব্লেম সলভিং প্রাকটিস করতে যেইসব জটিল সল্যুশন আমরা ব্যবহার করি - তার কতটুকু জবের দৈনন্দিন সত্যিকার কাজে গিয়ে আসলে লাগে? আমার ধারণা খুব একটা না। অন্তত আমার লাগে না। কিন্তু তাই বলে আমি বলছি না যে এইগুলো শেখার দরকার নাই, প্র্যাক্টিস করা বৃথা - মাথা কাজ করানোর জন্য এইসব খুবই জরুরি। আর কাজের জায়গায় যখন কোনো একটা প্রব্লেম সল্ভ করতে গিয়ে আগের শেখা কোনো এলগোরিদম, ডাটা স্ট্রাকচার কিংবা টেকনিক কাজে লাগে, তখন আসলেই খুব ভালো লাগে। এতো ভূমিকা দেয়ার কারণ হচ্ছে, কয়েকদিন আগে আমার তাই-ই হয়েছিল, জেনেরিক প্রব্লেমটা আর সল্যুশনটা শেয়ার করার লোভ সামলাতে পারছি না। নিচে দিচ্ছি:

প্রব্লেম: ধরা যাক, n সংখ্যক লিস্টে কিছু নম্বর আছে। আপনাকে সেগুলো (পাইথনে) list of lists আকারে ইনপুট দেয়া হবে। আরেকটা সংখ্যা, p দেয়া হবে। আপনার কাজ হবে, p লেংথ-এর একটা লিস্ট রিটার্ন করা,  যেখানে ইনপুটের n লিস্টের সবগুলো থেকে প্রায় সমান সংখক এলিমেন্ট নিতে হবে। আর ডুপ্লিকেট থাকতে পারবে না। দুইটা উদাহরণ দেই:

কেস ১:
list_of_lists = [[1, 2, 3], [3, 4, 5], [6, 7]], p = 6;
expected output = [1, 3, 6, 2, 4, 7] 

কেস ২
list_of_lists = [[1, 2, 3], [3, 4, 5], [6, 7]], p = 7;
expected output = [1, 3, 6, 2, 4, 7, 5]

প্রব্লেমটা আশাকরি বোঝা গেছে। কেস-১ সিম্পল। সবগুলা ইনপুট লিস্ট থেকে ২ টা করে নিয়ে ৬ সাইজের আউটপুট লিস্ট তৈরী করলেই হলো। কেস-২ একটু জটিল,  যেহেতু আউটপুট লিস্টে ডুপ্লিকেট থাকতে পারবে না, ইনপুটের দ্বিত্বীয় লিস্ট থেকে 5 নিয়ে ৭ সাইজের লিস্ট তৈরী করা লাগলো। 

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

সল্যুশন: প্রথমেই খেয়াল করে দেখি যে একটা পরিচিত আলগোরিদমের সাথে প্রব্লেমটার মিল আছে। merge sort আলগোরিথমের মার্জ অংশে আমরা দুইটা সর্টেড লিস্ট থেকে একটা আউটপুট লিস্ট বানাই। আর এখানেও অনেকটা তাই, শুধু দুইটার বদলে n-সংখ্যাক লিস্ট, আর সর্টেডর বদলে শর্ত হচ্ছে  আউটপুট লিস্ট ইউনিক হতে হবে। অর্থাৎ, যতক্ষণ p সাইজের লিস্ট হচ্ছে না, ততক্ষন এক এক করে প্রতিটা n -লিস্টের এলিমেন্ট নিবো, একটা set ব্যবহার করে ইউনিক কিনা টেস্ট করে আউটপুট লিস্টে এপেন্ড করতে থাকবো। আর যদি ইউনিক না হয়, তাহলে লিস্টের পরের এলিমেন্টটা নিবো, যতক্ষণ লিস্টে এলিমেন্ট থাকে। কিছু কর্নার কেস বাদে, এইটাই বেসিক সল্যুশন।

কর্নার কেস গুলো কি? কয়েকটা হতে পারে, যেমন: হাতের লিস্টে যদি এলিমেন্ট না থাকে? যদি আউটপুট p -র থেকে ইনপুট n লিস্টের সাইজ কম: (n < p) হয়।  যদি লিস্ট গুলোতে ডুপ্লিকেট সংখ্যা বেশি থাকে  - মূলত এই কয়টাই। কিছু চেক অ্যাড করে সেটাও হ্যান্ডেল করা যাবে। 

বাকিটা না পড়ে, আপনি কি একটু কোডটা ইমপ্লিমেন্ট করার চেষ্টা করবেন? আমার ধারণা করলেই কিছু ইম্প্রোভমেন্ট আপনার মাথায় আসবে। যেটা আমি নিচে দিচ্ছি।

প্রতিটা লিস্টের কোন ইনডেক্স-এ আছি, সেটা ম্যানেজ করা একটু ঝামেলা হবে। একটু চিন্তা করতেই  মাথায় আসলো যে আমি পাইথনের generator ব্যবহার করে সেটা সল্ভ করতে পারি। ইনপুট n -লিস্টের প্রতিটাকে যদি আমি শুরুতেই  generator -এ কনভার্ট করি, আর next() কল করে এলিমেন্ট বের করে আনি, তাহলে পাইথনই ইনডেক্স ম্যানেজ করবে, আমার আর সেটা হ্যান্ডেল করতে হবে না। একটা ঝামেলা হয়তো হবে, যদি জেনারেটরে এলিমেন্ট না থাকে, তাহলে exception থ্রো করবে। ভাবলাম, সেটা নাহয় try-except এ ঢুকিয়ে হ্যান্ডেল করবো। কোডের চেহারা অনেকটা এইরকম হলো:



কোডের লিংক : https://replit.com/join/vhqitodokp-ishtiaquehussai

এরপর আরেকটু ভাবার পর মনে হলো, একটা কিউ ব্যবহার করে তো কোডটা আরো ভালো করা যায়, count ব্যবহার করে এতো জটিল করার তো দরকার নাই। আগে সেই কোডটার স্ক্রিনশট দিচ্ছি, তারপর নিচে ব্যাখ্যা করছি:


 

আইডিয়াটা হচ্ছে, জেনেরেটরগুলোকে শুরুতে একটা কিউতে ঢুকিয়ে রাখলাম। এরপর যতক্ষণ output লিস্টের সাইজ p  না হয় এবং কিউয়ে এলিমেন্ট থাকে, ততক্ষন ডিকিউ করে কিউ থেকে জেনেরেটর বের করে নিলাম। এরপর জেনারেটর থেকে এলিমেন্ট next() কল করে নিলাম, এলিমেন্ট ইউনিক হলে output লিস্টে, set -এ এপেন্ড, অ্যাড করে নিলাম। তারপর হাতের জেনেরেটরকে আবারো কিউ-এ ঢুকিয়ে দিলাম। আর যদি, এলিমেন্ট ইউনিক না হয়, তাহলে জেনেরেটর থেকে next ()- কল করে আবারো একই কাজ করতে থাকলাম (while True) । যদি কখনো next() কল করে জেনারেটরে এলিমেন্ট না পাই, তখন জেনারেটর StopIteration এক্সেপশন থ্রো করবে। সেই এক্সেপশন হ্যান্ডেল করার জন্য কিছুই না, শুধু হাতের জেনেরেটরকে পুনরায় আর কিউতে অ্যাড না করলেই হবে - অর্থাৎ, এলিমেন্ট যখন আর নাই-ই তাহলে সেটা কিউ থেকে ফেলে দিতে হবে।    

আমরা চাইলে except Exception লিখেও কাজটা করতে পারতাম। তবে ভালো কোডিং প্রাকটিস হচ্ছে, too-broad-exception হ্যান্ডেল না করে স্পেসিফিক এক্সেপশন হ্যান্ডেল করা। জেনেরেটরে এলিমেন্ট না থাকলে next() যেহেতু StopIteration এক্সেপশন থ্রো করে, কাজেই সেটা হ্যান্ডেল করাই ভালো। 

সবশেষ: গতরাতে আমার বন্ধু মিথুনের সাথে প্রব্লেমটা নিয়ে আলাপ করছিলাম। মিথুন ইউনিভার্সিটি অফ মেমফিস, টেনেসিতে পিএইচডি করছে। আলাপ করতে গিয়ে আরেকটা আইডিয়া আমাদের মাথায় আসলো। জেনারেটার ছাড়াই শুধু কিউ দিয়েই তো প্রব্লেমটা আসলে সল্ভ করা যায়! ইনপুট list_of_lists 'র প্রতিটা লিস্টের এলিমেন্টগুলোকে কিউয়ে ঢুকিয়ে, পরে সেই কিউ গুলোকে আরেকটা কিউ-এ ঢুকিয়ে queue of queues বা nested queue  করেও তো প্রব্লেমটা সল্ভ করা যায়। চমৎকার আইডিয়া! কারো পাইথনে জেনেরেটর'র আইডিয়া না থাকলে, এভাবেও প্রব্লেমটা সল্ভ করা যাবে। নিচে কোডের স্ক্রিনশট দিচ্ছি:





আর সবগুলো ভার্শনের কোডের লিংক নিচের লিংকে পাওয়া যাবে:
https://replit.com/join/vhqitodokp-ishtiaquehussai

সবাইকে ধন্যবাদ!
--ইশতিয়াক, ৭ ব্যাচ, সিএসই, ডিইউ    

প্রবলেম সলভিং, পাইথন প্রোগ্রামিং, সিস্টেম ডিজাইন আর মেশিন লার্নিং শেখার জন্য (আমার মতে) বেস্ট রিসোর্স

প্রবলেম সলভিং, পাইথন প্রোগ্রামিং, সিস্টেম ডিজাইন আর মেশিন লার্নিং শেখার জন্য (আমার মতে) বেস্ট রিসোর্স 
বুধবার, ১৫ জুন ২০২২



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

যেমন প্রথমেই বলি, প্রবলেম সলভিং -এর রিসোর্স -এর ব্যাপারে। এই ব্যাপারে আমি আগে একটা ব্লগ লিখেছিলাম। সেখানে অনেকগুলো রিসোর্সের লিংক দিয়েছিলাম। কিন্তু এখন যেই রিসোর্স পেয়েছি, সেটা বেস্ট। আগের গুলার সাথে এইটার কোনো তুলনাই চলে না (ওই ব্লগ পোস্টে এইটার লিংক দিয়ে আপডেট করে দিয়েছি)। NeetCode.io  - এই ওয়েবসাইটটার বয়স ২ বছরও না। এর সাথের YouTube চ্যানেল এরমধ্যেই প্রায় ১৬০, ০০০ সাবস্ক্রাইবার ছাড়িয়েছে। আমি সিওর কিছুদিনের মধ্যেই মিলিয়ন ছাড়িয়ে যাবে। কেন এতো ভালো? উপরের ভিডিওতে আমি তা আলাপ করেছি, দেখে নিতে পারেন।  

পাইথনের অ্যাডভান্স ফীচার, পাইথন দিয়ে ডিজাইন প্যাটার্ন, সফটওয়্যার ডেভেলপমেন্ট শেখার জন্য ArjanCodes এই YouTube চ্যানেল বেস্ট। ভদ্রলোক প্রত্যেকটা টপিক কোড করে করে, টু-দা-পয়েন্ট বুঝিয়ে দেয়। মজাও করে মাঝে মাঝে। 

সিস্টেম ডিজাইন নিয়ে আমার বরাবরই দুর্বলতা। Alex Xu -র বইগুলা কিনেছি পড়বো বলে। কিন্তু সময় করতে পারি না। উনার সাপ্তাহিক নিউজলেটার, যেখানে যেকোনো একটা টপিকের উপর খুব সুন্দর করে ১ পৃষ্ঠায় ছবি দিয়ে ব্যাখ্যা করা থাকে - বেশ কাজের। গতকালকে ভদ্রলোক ঘোষণা দিলেন যে উনি YouTube চ্যানেল খুলছেন, যেখানে ওই টপিক গুলার উপর ভিডিও বানাবেন। এক দিনেই ২৩,০০০-এর উপর সাবস্ক্রাইবার হয়ে গেছে।  আমিও সাবস্ক্রাইব করেছি। 

অনেকদিন ধরেই মেশিন লার্নিং শিখবো বলে চিন্তা করেছি। মাঝে মাঝে কিছু ব্লগ, বইয়ের চ্যাপ্টার এমনকি কোর্স শুরু করেও শেষ করি নাই। সব সময়ই মনে হয়েছে আমার স্ট্যাটিসটিক্স আর ম্যাথের বেসিক (যেমন ক্যালকুলাস) ভালো জানা নাই  - আমারে দিয়ে হবে না। YouTube -এ StatQuest এই চ্যানেলে ভিডিও গুলা দেখে ইদানিং সেই ভয়টা কিছু কাটছে। জোশ স্টারমার নামের এই লোক একদম বেসিক থেকে শুরু করে, ধাপে ধাপে মেশিন লার্নিং শেখায়। ভদ্রলোক নিজে আমেরিকার বিখ্যাত ইউনিভার্সিটি অফ নর্থ ক্যারোলিনা এট চ্যাপেল হিল ইউনিভার্সিটির জেনেটিক্স -এর পিএইচডি স্টুডেন্ট অবস্থায় ভিডিও বানানো শুরু করেছিল। সাবজেক্টের উপর যে অসম্ভব দখল আছে, ভিডিও দেখলেই বুঝা যায়। আমার মতে বেস্ট রিসোর্স! ভিডিও গুলা দেখার জন্য ভিডিও ইনডেক্স আছে (অর্থাৎ কোন ভিডিও দেখার পর কোনটা দেখা উচিত -সেটার রোডম্যাপ)। আরেকটা বই আছে,  The StatQuest Illustrated Guide to Machine Learning (PDF) - অনেকটা কমিক্স টাইপ বই, চমৎকার। কারো কেনার সুযোগ থাকলে কেনা উচিত। 

আপনাদের কারো এইরকম (বা এর থেকেও ভালো) কোনো রিসোর্স জানা থাকলে কমেন্টে জানানোর অনুরোধ থাকলো।ধন্যবাদ!


কোনো কিছু ইন্স্টল্ না করে পাইথনে সহজে পাই-চার্ট বানানোর উপায়

কোনো কিছু ইন্স্টল্ না করে পাইথনে সহজে পাই-চার্ট বানানোর উপায় 
বৃহস্পতিবার, ১৭ মার্চ, ২০২২

রাজ্যের কাজ জমে আছে। তাও ব্লগ লিখতে বসেছি। একটা পেপার লেখার কাজ শেষ করতে হবে। পেপারে দুইটা পাই চার্টের ছবি দিতে হবে। ভাবছিলাম Microsoft Excel -এ ডাটা বসিয়ে পাই-চার্ট বানিয়ে ফেলি। কিন্তু পরে ভাবলাম, নাহ, পাইথন দিয়েই পাই-চার্ট বানাবো। এর আগে আরেকটা পেপারে পাইথন দিয়ে বেশ কয়েকটা গ্রাফ বানিয়ে ব্যবহার করেছিলাম। দেখতে বেশ ভালো হয়েছিল গ্রাফ গুলো। তাই-ই সময় লাগবে জেনেও সাহস করে বসলাম। কিছুক্ষন ইন্টারনেট ঘেঁটে Google Colab -এ চার্ট গুলো বানালাম। পুরো কাজটা করার জন্য কম্পিউটারে কিছুই ইনস্টল করা লাগে না। কারণ Google Colab -এ পাইথন সহ matplotlib লাইব্রেরি ইন্স্টল্ করাই আছে। 


টার্গেট পাই চার্ট 

কোড খুব বেশি না। নিচে পুরো কোডটি দিয়ে দিলাম।  

import matplotlib.pyplot as plt

bug_types = ['User Interface (UI)', 'Functional', 'Security', 'Performance']
bug_count = [17, 20, 3, 1]

colors = ['tab:green', 'tab:blue', 'tab:orange', 'tab:red']

plt.pie(bug_count,
labels=bug_types,
autopct='%.2f%%',
pctdistance=0.6,
colors=colors)
plt.axis('equal')
plt.show()

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


 

 
 

পাইথন ডেকোরেটর: পর্ব - ১

পাইথন ডেকোরেটর: পর্ব - ১
২১ জুন, সোমবার, ২০২১

বেসিক পাইথন আমি মোটামুটি জানি। টুকটাক কাজও করেছি। কিন্তু পাইথনের এডভান্সড জিনিসপত্র শিখবো শিখবো করেও শেখা হচ্ছিল না। বেসিক পাইথনের আমি যতটুকু জানি, তার কমবেশি আমার "সহজ বাংলায় পাইথন" আর "সহজ বাংলায় পাইথনে ডেটা স্ট্রাকচার" ইউটিউব ভিডিও সিরিজের ভিডিওগুলোতে আলোচনা করেছি। এই ভিডিও গুলোর একটা সুবিধা হচ্ছে, অনেকেই অনেক সময় কমেন্ট করে নতুন কোনো টপিকের উপর ভিডিও বানানোর অনুরোধ করেন। সেইরকম একটা অনুরোধ ছিল এই পাইথন ডেকোরেটর। কাজেই বুঝতে পারছেন, আমি নিজে শিখে আজকে কিছু লেখার চেষ্টা করছি। কোত্থেকে শিখছি সেটার সম্পর্কেও একটু বলি। আমাদের ডিপার্টমেন্টের জুনিয়র, ফরহাদ নাঈমের কাছ থেকে পাইথনের উপর লুসিয়ানো রামালহো-র লেখা 'ফ্লুয়েন্ট পাইথন' বইটার নাম জেনেছিলাম। ফরহাদ খুবই কাজের একটা ছেলে, ওর টেকনোলজির উপর দখল অনেক ভালো। ওর কথাতেই বইটা একটু ঘাঁটাঘাঁটি করে দেখে আমি মুগ্ধ। খুবই ভালো বই। আজকের পুরো লেখাটাই এই বইয়ের 'Function Decorators and Closures' - চ্যাপ্টারের প্রথম অংশ থেকে নেয়া - নিজের মতো করে লেখার চেষ্টা করছি।    

পাইথন ডেকোরেটর বোঝার জন্য কয়েকটা জিনিস জানতে হবে: সবগুলোই এক এক করে উদাহরণ দিয়ে পরিষ্কার করার চেষ্ঠা করছি: 

  • ১. পাইথন 'ফার্স্ট ক্লাস' ফাঙ্কশন সাপোর্ট করে  - অর্থাৎ, পাইথনে ফাঙ্কশন একটা অবজেক্ট। 

একটা ফাঙ্কশনকে কোনো ভ্যারিয়বলে -এ এসাইন করা, অন্য ফাঙ্কশনে প্যারামিটার হিসাবে পাস্ করা, অন্য ফাঙ্কশন থেকে রিটার্ন করা, কোনো ডেটা স্ট্রাকচার (যেমন, পাইথন লিস্ট, ডিকশনারী, সেট ইত্যাদি) -এ স্টোর করা যায়। নিচের ছবি ১ ও ২ খেয়াল করলে প্রথম দুইটা ব্যাপার পরিষ্কার হবে। 


ছবি ১: একটা ফাঙ্কশনকে অন্য ভেরিএবলে এসাইন করিয়ে, সেটা দিয়ে অন্য নামে কল করা যায় 


ছবি - ২ -, লাইন ১৪ তে  bar() ফাঙ্কশন foo ফাঙ্কশনকে প্যারামিটার হিসাবে নিলো, নিজে 'Inside bar  ...' প্রিন্ট করে তারপর foo ফাঙ্কশন কল করলো, যেটা 'Inside foo  ...' প্রিন্ট করলো।       

ছবি ২: একটা ফাঙ্কশন অন্য ফাঙ্কশনকে প্যারামিটার হিসাবে নিয়ে কল করতে পারে 

  • ২. দুটো ফাঙ্কশন মাথায় রাখতে হবে, প্রথমটা হচ্ছে টার্গেট ফাঙ্কশন - যেটাকে ডেকোরেট (বা সাজানো) হবে, আর দ্বিতীয়টা হচ্ছে ডেকোরেটর ফাঙ্কশন, যেটা কিনা টার্গেট মেথডকে ডেকোরেট করবে বা সাজাবে।

আর এজন্য টার্গেট মেথডের শুরুতে '@' চিহ্ন ব্যবহার করে ডেকোরেটর মেথডের নাম লিখে দিতে হয়। এযেন টার্গেটের কানে দুল পরিয়ে সাজিয়ে দেয়া 😀। আসলে ডেকোরেটর মেথড টার্গেট মেথডকে প্যারামিটার হিসাবে নেয়। ডেকোরেটর মেথড নিজের মধ্যে অন্য কিছু করতে পারে, তারপর পাস্ হওয়া টার্গেট মেথড কল করতে পারে। সব কাজ শেষ হলে, রিটার্ন করতে পারে অরিজিনাল টার্গেট মেথড, অথবা অন্য inner মেথড (এ ব্যাপারে পরে বলছি)।   

ছবি ৩: ডেকোরেটর  মেথড টার্গেট মেথডকে প্যারামিটার হিসাবে নেয় 

  • ৩. ডেকোরেটর ফাঙ্কশন যে মডিউল-এ ডিফাইন করা আছে, সেই মডিউল লোড হওয়ার সময়ই, অর্থাৎ ইম্পোর্ট করার সময় (import time) ডেকোরেটর ফাঙ্কশন আপনা-আপনি 'কল' হয়ে যায়।
ছবি -৩ খেয়াল করলে দেখবেন, কেউ কিন্তু টার্গেট কিংবা ডেকোরেটর কোনো মেথডকেই কল করে নাই, কোনো কিছু প্রিন্ট করে নাই। কিন্তু তারপরও আউটপুট দেখলে দেখবেন 'Inside decorator  ...' প্রিন্ট হয়ে বসে আছে।  তার কারণ, কোড লোড হওয়া মাত্রই সব ডেকোরেটের মেথড আপনা-আপনি কল হয়ে যায়।  আর একারণেই আমরা দেখছি, 'Inside decorator ...' প্রিন্ট আছে।  

  • ৪. পাইথন ডেকোরেটর আর কিছুই না, সূত্র আকারে মনে রাখতে চাইলে:  টার্গেট = ডেকোরেটর(টার্গেট). 

অর্থাৎ টার্গেট ফাঙ্কশনকে ডেকোরেটর ফাঙ্কশনের প্যারামিটার হিসাবে পাঠিয়ে দিয়ে, ডেকোরেটরের নিজস্ব কোড যোগ করে (অর্থাৎ সাজিয়ে নিয়ে) পরে ডেকোরেটর ফাঙ্কশন থেকে কিছু একটা রিটার্ন করিয়ে আবার টার্গেট ফাঙ্কশনের একই নামের ভ্যারিয়েবলে এসাইন করিয়ে দেয়া হয়। চাইলে একই টার্গেট ফাঙ্কশন বা অন্য একটা ইনার ফাঙ্কশন রেফারেন্স রিটার্ন করা যায়।  এতে করে যখন কেউ পরে আবার টার্গেট ফাঙ্কশন কল করবে, টার্গেট() - তখন ডেকোরেটর ফাঙ্কশন থেকে রিটার্ন করা ফাঙ্কশনটা রান করবে।  রামালহোর বইয়ের একটা স্ক্রিনশট না দিয়ে পারছি না :

রামালহোর বইয়ের স্ক্রিনশট: এক কথায় পাইথন ডেকোরেটরের ব্যাখ্যা  


ছবি ৪: ডেকোরেটর মেথডের মাধম্যে টার্গেট মেথড কল করা 

উপরের ছবি ৪ দেখে ব্যাপারটা আরেকটু বুঝিয়ে বলা যাক। খেয়াল করুন, লাইন ২৫ -এ যখন আমরা target() কল করছি, তার আগে কিন্তু 'target' ভ্যারিয়েবলে ডেকোরেটর মেথড থেকে রিটার্ন করা func রেফারেন্স করিয়ে নিচ্ছি। অর্থাৎ, target() কল করলেও আসলে কিন্তু func() ফাঙ্কশন কল হচ্ছে। আর এক্ষেত্রে দুটো একই 'target' ফাঙ্কশন হওয়ায় আউটপুট একই হবে, কিন্তু চাইলেই ডেকোরেটর মেথড থেকে আমরা অন্য inner মেথড রিটার্ন করিয়ে নিয়ে সম্পূর্ণ ভিন্ন কিছু আউটপুট দিতে পারতাম। যেমন নিচের ছবিতে (ছবি ৫), মূল টার্গেট মেথডকে সম্পূর্ণ সরিয়ে দিয়ে 'Inside inner  ...' প্রিন্ট করিয়ে নিচ্ছি:

  

ছবি ৫: টার্গেট মেথডের ব্যবহার (behavior) ডেকোরেটরের inner মেথড দিয়ে পাল্টিয়ে দিলাম 


আর লাইন ২৫ -এর এই কাজটা @ চিহ্ন দিয়ে ডেকোরেটর ফাঙ্কশনের নাম লিখে ব্যাকগ্রাউন্ডে করে ফেলা যায়। যেমন নিচের ছবিতে লাইন ২৫ মুছে দিয়েও একই আউটপুট পাওয়া যাচ্ছে। 

ছবি ৬: ইন্ডিরেক্টলি বা ঘুরিয়ে ডেকোরেটর ফাঙ্কশন কল করা হচ্ছে 

আচ্ছা, কিন্তু এই ঘুরিয়ে কাজ করার দরকার বা উপকারিতাটা কি? ডেকোরেটরের পুরো শক্তি বা উপকারিতা একটা ব্লগ পোস্টে লিখে বোঝাতে গেলে লম্বা হয়ে যাবে। আজকের পোস্টে তাই inner ফাঙ্কশন ব্যবহার না করে, অর্থাৎ মূল টার্গেট মেথড ঠিক রেখে (ছবি ৩- এর মতো) কিভাবে ডেকোরেটর ব্যবহার করে একটা ডিজাইন প্রবলেম সল্ভ করা যায়, সেটা লিখছি। পরে কোনো একদিন বাকি গুলো নিয়ে লিখবো, ইনশাআল্লাহ। 

ধরা যাক ডিজাইন প্রবলেমটা অনেকটা এই রকম : আপনি একটা সুপার স্টোরের চেকআউট সিস্টেম ডিজাইন আর ইমপ্লিমেন্ট করবেন। আইডিয়া হচ্ছে, আপনার স্টোরে কাস্টমারেরা একটা শপিং কার্ট-এ বাজার করে চেকআউট কাউন্টারে আসবে। সব আইটেম স্ক্যান করা হয়ে গেলে আপনি মোট দামের উপর কিছু ডিসকাউন্ট দিতে চান।  যেমন: আপনার 'বান্ধা' বা রেগুলার  কোনো কাস্টমারের জন্য ৫% রিওয়ার্ড ডিসকাউন্ট দিতে চান; কোনো কাস্টমার একই আইটেম ২০ টার বেশি কিনলে সেগুলোর উপর ১০% ডিসকাউন্ট দিতে চান, ইত্যাদি। কিন্তু শর্ত হচ্ছে, একবারে শুধু একটা ডিসকাউন্ট প্রযোজ্য। দুইয়ের বেশি কুপন থাকলে সবচেয়ে বেশি ডিসকাউন্ট যেই কুপনে পাওয়া যাবে, শুধু সেইটাই মূল মূল্যের উপর ছাড় হিসাবে প্রয়োগ হবে। আর আপনি চান, খুব সহজেই পুরোনো কোনো 'অফার' বাদ দিয়ে অন্য নতুন 'অফার' যোগ করবেন (যেমন ঈদে বা পূজা কিংবা বড়দিনের সময় ১০% ছাড়)। এই কোডটা খুব সহজেই পাইথন ডেকোরেটর দিয়ে করে ফেলা যাবে।  

খুব বেশি ব্যাখ্যা না করে সরাসরি 'Cutomer', 'Item' আর 'Cart' ক্লাস গুলো নিচে দিয়ে দিচ্ছি। সাধারণ আইডিয়া, একজন কাস্টমারের নাম, রিওয়ার্ড পয়েন্ট, আর শপিং কার্ট -এর রেফারেন্স থাকবে 'Customer' ক্লাসে।  বাজারের আইটেম-এর ডেসক্রিপশন, দাম, আর সংখ্যা (ডিফল্ট ১ টা) থাকবে 'Item' ক্লাসে।  আর 'Cart' ক্লাসে আইটেমে অবজেক্টের  একটা লিস্ট থাকবে। কাস্টমার বাজার নিয়ে চেকআউট-এ আসলে তার কার্টে থাকা আইটেম গুলোর দাম আর সংখ্যা গুণ করে মোট দাম হিসাব করা হবে।  

ছবি ৭ : সবগুলো ক্লাস একটা পাইথন ফাইলে লিখে রেখেছি 

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

ছবি ৮: ডিসকাউন্ট অফার হিসাব করার ফাঙ্কশনগুলো 

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

দুটো কাজই আসলে ডেকোরেটর দিয়ে করা যায়। একটা ডেকোরেটর ফাঙ্কশন ইমপ্লিমেন্ট করা যায়, যার কাজ হবে ফাঙ্কশনগুলোকে একটা লিস্টে অ্যাড করা।  আর প্রতিটি 'ডিসকাউন্ট' মেথডের শুরুতে @ চিহ্ন দিয়ে ওই ডেকোরেটরের নাম দিয়ে দিলেই হবে। মডিউল ইম্পোর্ট করার সময় (import time) আপনা-আপনি সবগুলো ডেকরেটর মেথড লিস্টে অ্যাড হয়ে যাবে। আর কোনো একটা 'অফার' বাদ দিতে চাইলে শুরুর @ চিহ্ন কমেন্ট আউট (comment out) করে দিলেই চলবে। তখন সেই অফার মেথড আর লিস্টে অ্যাড হবে না।  নিচের কোডে (ছবি ৯) খেয়াল করুন, যেহেতু ডেকোরেটর মেথড টার্গেট মেথড কল করছে না, শুধু রিটার্ন করছে, তাই টার্গেট মেথডের বিহেভিয়ার বা ব্যবহার বদলাচ্ছে না।   

ছবি ৯: ডেকোরেটর ব্যবহার করে promos লিস্টে ডিসকাউন্ট অফার মেথডগুলো যোগ করা হচ্ছে 

খেয়াল করুন, লাইন ২৬ - এ discount মেথড promos লিস্টে থাকা এক একটা ডিসকাউন্ট মেথড কল করবে আর শেষে সর্বোচ্চ ডিসকাউন্ট এমাউন্ট রিটার্ন করবে।  

এইবার, একটা ক্লায়েন্ট কোড লিখে কোডটা রান করা যাক। নিচের ছবি ১০-এ আমরা কয়েকটা আইটেম অবজেক্ট তৈরি করে নিলাম। তারপর একটা Cart অবজেক্ট তৈরি করে আইটেম গুলো অ্যাড করে নিচ্ছি।  এইবার লাইন ১২-তে একজন কাস্টমার 'জসিম' তৈরী করলাম, ধরে নেই উনার রিওয়ার্ড পয়েন্ট ১০০। এবার ডিসকাউন্ট বাদে মূল্য বের করলাম তারপর ডিসকাউন্ট এপ্লাই করলাম।   

ছবি ১০: ডেকোরেটর ব্যবহার করে সর্বোচ্চ ডিসকাউন্ট প্রয়োগ 

খেয়াল করুন, কোড রান করার শুরুতেই ডেকোরেটর গুলো আপনা-আপনি রান হয়ে যাচ্ছে, আর ডিসকাউন্ট প্রমোশন গুলো লিস্টে অ্যাড হয়ে যাচ্ছে।  সবশেষে, লাইন ১৭-তে যখন 'discount()' মেথড কল হচ্ছে, তখন সর্বোচ্চ যেই ডিসকাউন্ট সেটা প্রয়োগ হয়ে দাম দেখাচ্ছে। ব্যস, হয়ে গেলো!!

যাই হোক, আশা করি বুঝতে পেরেছেন। পুরো কোডের Repl.it লিংক নিচে দিয়ে দিচ্ছি।  কোড গুলো ক্লোন করে নিয়ে নিজেরা রান করলে আশাকরি আরো ভালোভাবে বুঝতে পারবেন।  

'ফার্স্ট ক্লাস' ফাঙ্কশন কনসেপ্ট -এর কোড: এই লিংকে 
ডিজাইন প্রবলেম -এর পুরো সল্যুশন কোড : এই লিংকে 

সবাইকে ধন্যবাদ !

ডাইক্স্ট্রা এলগোরিদম: ইমপ্লিমেন্ট করতে গিয়ে যা যা শিখলাম!

 ডাইক্স্ট্রা এলগোরিদম: ইমপ্লিমেন্ট করতে গিয়ে যা যা শিখলাম 
১১ মে, ২০২১, মঙ্গলবার 

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

ডাইক্স্ট্রা এলগোরিদম (Dijkstra Algorithm) - এলগোরিদম কোর্সে খুবই কমন একটা টপিক। গ্রাফে একটা নোড থেকে বাকি সব নোডে যাওয়ার সবচেয়ে ছোট (বা শর্টেস্ট) পথ খুঁজে বের করাই এই এলগোরিদমের কাজ। এর কিছু সীমাবদ্ধতা আছে (যেমন, নেগেটিভ এজ সামলাতে পারে না) - এসব বাদ দিলে খুবই কার্যকরী একটা এলগোরিদম।  'লোভী পদ্ধতির' বা 'Greedy Strategy' এলগোরিদম বোঝার জন্যও ডাইক্স্ট্রা এলগোরিদম উদাহরণ হিসাবে শেখা উচিত। যদিও আমি নিচে ব্যাখ্যা করছি, তবুও আপনার জানা না থাকলে, কিংবা এই মুহুর্তে ডাইক্স্ট্রা এলগোরিদমটা মনে না থাকলে চট করে শাফায়াত আশরাফের বাংলা ব্লগ পড়ে নিতে পারেন। শাফায়াত আমাদের ডিপার্টমেন্টের জুনিয়র। ওর সাথে আমার কোনোদিন দেখা হয় নাই। কিন্তু ওর সাথে ওর এই ব্লগের কল্যানেই যোগাযোগ আছে। ওর গ্রাফের উপর বাংলা বইটাও খুবই চমৎকার। আমি ক্লাসের প্রিপারেশন নেয়ার জন্য ওর বইটা ব্যবহার করেছি। মায়ের ভাষায় কোনো কিছু পড়লে অনেক সহজবোধ্য হয়।  কিন্তু শাফায়াতের এলগোরিদম আর গ্রাফের উপর জ্ঞান আর লেখার হাত দুটো ভালো বলেই বইটা আরো ভালো হয়েছে।  

যাই হোক, খুব সংক্ষেপে ডাইক্স্ট্রা এলগোরিদম মূল আইডিয়াটা লেখার চেষ্টা করছি। Breadth First Search বা BFS হচ্ছে এর মূল ইঞ্জিন। BFS আবার কি? একটা গ্রাফের একটা নোড থেকে তার সবগুলো প্রতিবেশী নোডকে এক এক করে visit বা ঘুরে তারপর অন্য নোডে যাওয়াটাই BFS। নতুন কোনো নোডে যাওয়া মাত্রই তাকে একটা চিহ্ন বা দাগ দিয়ে দিতে হয় (রং gray বা ছাই করে দিয়ে), যাতে পরবর্তীতে আর ভিসিট করা না লাগে। আর একটা নোডের সবগুলো প্রতিবেশী নোড দেখা শেষ হয়ে গেলে আরেকটা চিহ্ন (রং কালো করে দিয়ে) 'complete' করে দিতে হয়।  আর এই পুরা কাজটা একটা কিউ (Queue) ডাটা স্ট্রাকচার দিয়ে ইমপ্লিমেন্ট করা হয়।  নিচে কোরমানের বইয়ের আলগোরিদমের ছবি দিয়ে দিচ্ছি (এইখানে d হচ্ছে মূল বা সোর্স নোড থেকে দূরত্ব/ধাপ আর 'পাই' আগের নোডের হিসাব রাখে):

      

ছবি ১: কোরমানের বই থেকে নেয়া [১]: BFS এলগোরিদম 

প্রথম যেটা খেয়াল করতে হবে, BFS এলগোরিদমে গ্রাফের প্রতিবেশী নোডগুলোর মধ্যে দূরত্ব ধরা হয় ১, অর্থাৎ এজের weight বা দূরত্ব সমান। এলগোরিদম রান করা শেষে একটা নোড থেকে বাকি নোড গুলো কত 'ধাপ' দূরে আর প্রতি নোডে যেতে কোন পথে যেতে হবে সেটা বের হয়।  কিন্তু ডাইক্স্ট্রা এলগোরিদম-এ গ্রাফের প্রতিটা নোডের সাথে তার প্রতিবেশী নোড শুধু সংযুক্তই না, ভিন্ন weight বা দূরত্বও দেয়া থাকে। সবচেয়ে কম দূরত্বে (বা Shortest Path) কিভাবে যাওয়া যায় সেটাই এই এলগোরিদম বের করে।  

উপরের এলগোরিদমে লাইন ১৩-র মতো 'একটা নোড ইতিমধ্যেই দেখা বা visit করা শেষ (রং সাদা না), তাই আর ঘাঁটানোর দরকার নাই '  - এই আইডিয়া বাদ দিয়ে ডাইক্স্ট্রা এলগোরিদম আরেকটু কৌতুহলী হয়। একটা নোডে যদি আরো কম খরচে (দরকার হলে অন্য আরেকটা নোড ঘুরে, কম দূরত্বে) পৌঁছানো যায়, তখন সেইটাই ভালো পথ - মূলত এই আইডিয়াটাই ডাইক্স্ট্রা এলগোরিদম। এই আপডেটটা নিচের 'Relax' মেথডটা করে থাকে:

ছবি ২: কোরমানের বই থেকে নেয়া[১]: সোর্স থেকে কোনো নোডের দূরত্ব (v.d) যদি অন্য আরেকটা নোড (u) ঘুরে কম দূরত্বে পৌঁছানো যায়, তাহলে সেইটাই ভালো পথ। w(u, v) নোড দুটোর দূরত্ব দেয়।  

আরেকটা কাজ ডাইক্স্ট্রা এলগোরিদম করে থাকে, সাধারণ কিউ (regular queue) ব্যবহার না করে প্রায়োরিটি কিউ ব্যবহার করে। কারণ যেহেতু আমরা শর্টেস্ট বা সবচেয়ে কম দূরত্বে পৌঁছাতে চাই, তাই সোর্স নোড থেকে কম দূরত্বের ভিত্তিতে একটা প্রায়োরিটি কিউ বা মিন-হিপ ব্যবহার করে কাজ করলে একই নোড বার বার ভিসিট বা ঘুরে দেখতে হয় না। আরেকটু বুঝিয়ে বলি: নিজের নোডে পৌঁছাতে যেহেতু কোনো দূরত্ব যাওয়া লাগে না, তাই শুরুতে সোর্স নোডের দূরত্ব শূন্য করে দিয়ে বাকি সব গুলো নোডের দূরত্ব অসীম করে দিয়ে প্রায়োরিটি কিউ বা মিন-হিপ তৈরী করা হয়।  এখন প্রায়োরিটি কিউ তে যতক্ষণ নোড আছে, প্রতিবার সবচেয়ে কম দূরত্বে পৌঁছানো যায় এমন নোড বের করে নিয়ে (Extract-Min ) (শুরুতে সোর্স নোড নিজেই থাকবে) সবগুলো প্রতিবেশীকে 'Relax' করিয়ে নিলেই হলো - সব সময় কম দূরত্বের নোডই অগ্রাধিকার পাবে, আর তা একবারই পাবে। আর এভাবে 'লোভী' হয়ে সব সময় কম দূরত্বের নোডকে নিয়ে চলতে থাকলে একসময় সব গুলো নোডে পৌঁছানোর শর্টেস্ট বা সবচেয়ে কমদূরত্বের পথ বের করে ফেলা যাবে। ব্যস, এইটাই ডাইক্স্ট্রা এলগোরিদম। নিচে এলগোরিদমটা দিয়ে দিচ্ছি:

ছবি ৩: কোরমানের বই থেকে নেয়া[১]: প্রায়োরিটি কিউ (বা মিন-হিপ) আর relax ফাঙ্কশন ব্যবহার করে ডাইক্স্ট্রা এলগোরিদম  

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

ছবি ৪: নোড অথবা ভারটেক্স ক্লাস 


এবার যেহেতু প্রতিটা এজের weight  বা দূরত্ব হিসাবে নিতে হবে, তার জন্য একটা টেবিল তৈরী করতে হবে।  ধরা যাক, আমরা নোড u  আর v - এর মধ্যে এজ, u - v  এজের জন্য 'uv' স্ট্রিং কী (Key) আর weight বা দূরত্ব ইন্টিজার (Value)  হিসাবে হ্যাশ ম্যাপ -এ রাখলাম।  নিচের কোড গ্রাফের নোড গুলো কে একটা ArrayList -এ রাখবে, কিছু সাপোর্টিং ফাঙ্কশন থাকবে যেগুলো দিয়ে নোড গুলোর মধ্যে এজ আর weight যোগ করা যায়।  বলে রাখা ভালো, নোড গুলোকে নাম্বার দিয়ে নাম দিয়ে রাখছি, অর্থাৎ 'u', 'v' ইত্যাদি না বলে 1, 2 ইত্যাদি হিসাবে রাখছি।   

ছবি ৫: গ্রাফ ইমপ্লিমেন্টেশন

এবার গ্রাফ তৈরি করার জন্য সব কোড রেডি। যতগুলো নোডের গ্রাফ তৈরী করতে চাই, ধরা যাক, ৫ নোডের গ্রাফ, তাহলে main মেথডে Graph(5) কল করে প্রথমে নোডগুলো তৈরী করে নিয়ে, তারপর ম্যানুয়ালি বা ধরে ধরে এজ আর এজের weight যোগ করে দেয়া যাবে।    

এবার আসি, ডাইক্স্ট্রা এলগোরিদম ইম্প্লিমেন্টেশনে। প্রথমে relax ফাঙ্কশন। ছবি ২ -এর এলগোরিদম নিচের কোডে ইমপ্লিমেন্ট করলাম। Relax করলে true আর নাইলে false রিটার্ন করবে। কেন? একটু পরে বুঝিয়ে বলছি।  

ছবি ৬: Graph ক্লাসের ভেতরে প্রাইভেট relax ফাঙ্কশন 

 
এরপর ছবি ৩-এর ডাইক্স্ট্রা এলগোরিদম ইমপ্লিমেন্ট করার জন্য আমাদের প্রায়োরিটি কিউ (মিন-হিপ) লাগবে। গুগলে একটু ঘাঁটাঘাঁটি করে পেলাম যে জাভাতে util লাইব্রেরিতে প্রায়োরিটি কিউ (মিন-হিপ) আগে থেকেই ইমপ্লিমেন্ট করা আছে। কিন্তু যেহেতু আমাদের সোর্স নোড থেকে অন্য নোডের দূরত্বের ভিত্তিতে প্রায়োরিটি কিউ বানাতে হবে, তাই এই ব্যাপারটা একটু বলে দিতে হবে। আর এই কাজটা একটা ক্লাস যেটা Comparator ইন্টারফেস ইমপ্লিমেন্ট করে সেটা লিখে করতে হয়। এর পর শুধু প্রায়োরিটি কিউ-এর প্যারামিটার হিসাবে সেই ক্লাস তা পাস্ করে দিলে হয়ে যায়।  নিচের কোড:


ছবি ৭: Graph ক্লাসের ভেতরে Comparator ইন্টারফেস ইমপ্লিমেন্ট করা inner ক্লাস 


এবার শেষমেষ ডাইক্স্ট্রা এলগোরিদম ইমপ্লিমেন্টেশনের পালা। ছবি ৩ -এর কোড ধরে কোডটা ইমপ্লিমেন্ট করে দিলাম। খেয়াল করবেন, প্রায়োরিটি কিউ প্যারামিটার হিসাবে আমাদের Comparator ক্লাস নিচ্ছে। 


ছবি ৮: Graph ক্লাসের ভেতরে ডাইক্স্ট্রা মেথড। 

ব্যস, হয়ে গেছে তাই না? টেস্ট করার জন্য কিছু কোড লিখে, একটা টেস্ট গ্রাফের উপর রান করলাম, ডিবাগ করে দেখলাম, সেটাও (সৌভাগ্য কিংবা দুর্ভাগ্য বশতঃ?) কাজ করলো! কিন্তু যেই না স্টুডেন্টদের কোড দিয়ে অন্য টেস্ট কেস রান করতে বললাম, এরর খাওয়া শুরু হলো।  কোড বার বার চেক করেও বের করতে পারছিলাম না কেন কাজ করছে না। কোড তো এলগোরিদম হিসাবে ঠিক ভাবেই ইমপ্লিমেন্ট করলাম। কি একটা বেইজ্জতির ব্যাপার! শেষমেষ না পেরে বললাম, আজকে থাক, আমি পরে কোড চেক করে বের করার চেষ্টা করবো কেন কাজ করছে না।  

ঐদিন ক্লাস শেষে বেশ কিছুক্ষন ডিবাগ করে, ডকুমেন্টস, StackOverflow ঘেঁটে পরে বাগটা ধরতে পারলাম। আপনারা একটু চেষ্টা করে দেখবেন নাকি ধরতে পারেন কিনা? 

যাই হোক, এতক্ষন ধরে আসলে কনটেক্সট দেয়ার চেষ্টা করলাম। এইবার মূল ব্যাপারটা বলি। বাগটা হচ্ছে প্রায়োরিটি কিউ ব্যবহার করায়। কোনো প্রায়োরিটি কিউ তার প্রপার্টি -- আমাদের ক্ষেত্রে সোর্স নোড থেকে সবচেয়ে কম দূরত্বে থাকা নোড রুটে (root) থাকবে - এই ব্যাপারটা মেইনটেইন করবে কেবল শুরুতে যখন প্রায়োরিটি কিউ তৈরী করা হয় আর যখন কোনো অপারেশন করা হয়, যেমন poll (extract) কিংবা add ইত্যাদি কল করার পর। 

আমরা যখন ছবি ৬ -এ, 'relax' মেথড কল করে নোডের ভেতরে 'distance' বা দূরত্ব আপডেট করে দিচ্ছি, তখন ধরে নিচ্ছিলাম যে প্রায়োরিটি কিউ নিজে থেকে আপডেট হয়ে, স্ট্রাকচার বা কাঠামো বদলে সবচেয়ে কম দূরত্বের নোড কে উপরে বা রুটে (root) নিয়ে আসবে। এটা সম্পূর্ণ ভুল ধারণা। প্রায়োরিটি কিউ -এর ডকুমেন্টেশনে কোথাও সেটা বলা নাই।  

তাহলে উপায়? StackOverflow ঘেঁটে সল্যুশন বের করলাম। যখন 'relax' মেথড নোডের distance আপডেট করে true রিটার্ন করবে তখন ম্যানুয়ালি প্রায়োরিটি কিউতে একটা অপারেশন চালিয়ে - যেমন poll করে রুট বের করে নিয়ে আবার সেই একই রুট নোড add করে দিয়ে আমাদের প্রপার্টি 'force update' করে নিতে হবে, তবেই কাজ হবে। নিচে পরিবর্তিত কোড, হাইলাইট করে দিচ্ছি :

    
ছবি ৯: বাগ ফিক্স করা পরিবর্তিত ডাইক্স্ট্রা এলগোরিদম ইমপ্লিমেন্টেশন 

এখন আশা করি বুঝতে পারছেন, ছবি ৬ - এ কেন relax মেথডে true/false রিটার্ন করা জরুরি ছিল। আমি ভাবছিলাম এই ছোট কিন্তু খুব জরুরি বিষয়টা কেন পরিস্কারভাবে বলা হলো না? পরে আরেকটু ভালো করে পড়ার পর পেলাম কোরমানের বইয়ে 'relax' -এর সাথে Decrease-Key ফাঙ্কশনের সম্পর্ক বলা আছে - যেটা কিনা প্রায়োরিটি কিউয়ের নোডের key (আমাদের ক্ষেত্রে distance-ই key) কমিয়ে দিয়ে কিউ আপডেট করে। 

ছবি ১০: কোরমানের বই থেকে নেয়া[১]। ঘুরিয়ে বলা হয়েছে যে relax পরোক্ষভাবে অন্য ফাঙ্কশন কল করে প্রায়োরিটি কিউয়ের প্রপার্টি মেইনটেইন করবে   

যাই হোক, ঝানু প্রোগ্রামাররা হয়তো শুরুতেই ব্যাপারটা ধরতে পেরেছেন। কিন্তু আমার মতো দুর্বল প্রোগ্রামাররা হয়তো কত ঘন্টা এই বাগের পেছনে সময় ব্যয় করেছেন কে জানে? দিন শেষে শিক্ষা: যখনই কোনো এলগোরিদম শিখবো, কোডে ইমপ্লিমেন্ট করে তবেই থামতে হবে; কোডে কোনো লাইব্রেরি ব্যবহার করলে তার ডকুমেন্টেশন ভালো করে পড়ে নিতে হবে, শুধু চট করে ফাঙ্কশন কল করে কোনো কিছু হয়ে যাবে  ধরে নেয়া ঠিক না; কোড বেশি বেশি টেস্ট করার কোনো বিকল্প নাই।  

সবাইকে ধন্যবাদ!
--ইশতিয়াক 

রেফারেন্স: 












গুগল কোল্যাব আর পাইথন এক্সেকিউটেবল চিটশীট:

গুগল কোল্যাব আর পাইথন এক্সেকিউটেবল চিটশীট:
২৭ জুন, শনিবার, 

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

গুগল কোল্যাব নিজেদের পরিচয় দেয় এইভাবে:

https://colab.research.google.com/notebooks/intro.ipynb

এটা ফ্রি! কারো গুগলে কিংবা জিমেইলে একাউন্ট থাকলেই হলো। গুগল ড্রাইভে গিয়ে নিচের ছবির মতো করে খুঁজে নিতে হয়। 

গুগল কোল্যাব যেভাবে খুঁজে নিতে হবে 


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

আমি কিছুদিন হলো হঠাৎ করেই YouTube -এ সহজ বাংলায় বেসিক পাইথনের উপর একটা ভিডিও সিরিজ বানাচ্ছি


পাইথনের উপর YouTube -এ একটা ভিডিও সিরিজ

লিংকডইন পোস্ট করে সবাইকে জানানোর পর সবার আগ্রহ, সাবক্রাইব করা আর কমেন্টে খুব উৎসাহ পাচ্ছি। আমি ভিডিও সিরিজটিতে, রিভিউ করার জন্য এরিক মাথিসের লেখা Python Crash Course — বইটার চিটশীট ফলো করছি।

Python Crash Course — বইটার চিটশীট

চিটশীটটা এমনিতেই খুবই ভালো। তারপরেও ভাবলাম যদি এটাকে এক্সেকিউটেবল করা যায় তাহলে আরো ভালো হবে।সেজন্যই একটা এক্সেকিউটেবল চিটশীট কোল্যাবে লিখছি।

এই দুটো সবার সাথে শেয়ার করার জন্যই আজকের ছোট এই লেখা। দুটোই চেক করে দেখার অনুরোধ থাকলো। সবাইকে ধন্যবাদ।







 

আমেরিকার বিশ্ববিদ্যালয় গুলোতে ফ্যাকাল্টি বা শিক্ষক নিয়োগ পদ্ধতি

আমেরিকার বিশ্ববিদ্যালয় গুলোতে ফ্যাকাল্টি বা শিক্ষক নিয়োগ পদ্ধতি
৩০ এপ্রিল, ২০২০, বৃহস্পতিবার


রোজা মাস, করোনা ভাইরাসের কারণে ঘরবন্দি। ঘুমানো দরকার।  কিন্তু তাও কিছু একটা লিখতে ইচ্ছা করছে, তাই ভাবলাম, এই বিষয়টা নিয়ে সংক্ষেপে কিছু লিখি। লেখাটা সফটওয়্যার ইঞ্জিনিয়ারিং-এর সাথে কোনোভাবেই যায় না, তাও লিখছি।

শুরুতেই বলে নেই, আমেরিকার শিক্ষক নিয়োগ মূলত দুই ট্রাকে হয় - টেনিয়র ট্র্যাক (Tenure) আর নন-টেনিয়র ট্র্যাক (Non-tenure)। টেনিয়র ট্র্যাকের ফ্যাকাল্টি বা শিক্ষকরা মূলত গবেষণা -নির্ভর কাজ করেন, পাশাপাশি পড়ান, ইউনিভার্সিটিতে বিভিন্ন সার্ভিস দেন।  ৫-৬ বছর এভাবে চলার পর, যদি এই সময়ে ভালো বেশ কিছু সংখ্যক পেপার পাব্লিশ করতে পারেন, ক্ষেত্র বিশেষে গবেষণা ফান্ড আনতে পারেন, মোটামুটি ভালো পড়াতে পারেন - তাহলে শেষমেষ তাঁদের চাকরি স্থায়ী বা পার্মানেন্ট হয়। আর একবার পার্মানেন্ট হলেই হলো, তাঁদের আর নির্দিষ্ট কোনো রিটায়ারমেন্ট বয়স থাকে না!

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

যাই হোক, আজকে লেখায় টেনিয়র ট্র্যাকের ফ্যাকাল্টি নিয়োগ নিয়ে কিছু লিখবো।  কিন্তু আমার ধারণা, নন-টেনিয়র ট্র্যাকের হাইয়ারিং মোটামুটি একই রকম হয়।

মূলত ৩ ধাপে শিক্ষক বাছাই করে নিয়োগ দেয়া হয়।  আর প্রতিটা ধাপে যা করা উচিত, আর যা করা উচিত না, সেটাই নিজের অভিজ্ঞতা থেকে লিখছি।

ধাপ ১: রেসুমে ও অন্যান্য কাগজপত্র জমা দেয়া :

শিক্ষক নিয়োগ বিজ্ঞপ্তি ইউনিভার্সিটি গুলোর নিজস্ব ওয়েবসাইট ছাড়াও অন্যান্য জব সাইটে দেয়া হয়।  আমি নিজে https://www.higheredjobs.com/ এই ওয়েবসাইট থেকে বিজ্ঞাপন দেখে এপলাই করেছিলাম। এছাড়াও শুনেছি https://chroniclevitae.com/ বেশ ভালো ওয়েবসাইট। আরো অনেক ওয়েবসাইট নিশ্চই আছে। যেমন ঢাকা বিশ্ববিদ্যালয়ে আমার সিনিয়র, নাসিম ভাই একটা ওয়েবসাইটের নাম কমেন্টে খেয়াল করিয়ে দিলেন: www.cra.org - এটা মূলতঃ আমেরিকা আর ক্যানাডাতে কম্পিউটার সায়েন্সের উপর ফ্যাকাল্টি, পোস্টডক ইত্যাদি পজিশনের এডভার্টাইসমেন্ট দিয়ে থাকে। যাই হোক, সাধারণত: জব গুলোর জন্য, একাডেমিক রেসুমে, একটা কভার লেটার, রিসার্চ আর টিচিং ফিলোসফি, ৩ জন রিকোমেন্ডর-র নাম জমা দিতে হয়।

যা করা উচিত:

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



ধাপ ২: প্রথম স্কাইপ কিংবা জুম ইন্টারভিউ কল:

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

যা করা উচিত:

  • আপনার রেসুমে থেকে যেকোনো বিষয়ের উপর জিজ্ঞেস করতে পারে।  তাই প্রথমেই সবগুলো পয়েন্ট, বিশেষ করে আপনি কোথাও আগে পড়িয়ে থাকলে, সেটা সম্পর্কে প্রশ্নের জন্য রেডি থাকবেন। 
  • ক্লাসে পিছিয়ে পড়া ছাত্র-ছাত্রী, নকল করলে কি করবেন, বিভিন্ন জাতি-বর্ণের ছাত্র-ছাত্রী আপনি কিভাবে সামলাবেন, অনলাইনে পড়াতে হলে কি করবেন -- ইত্যাদি বিহেভিওরাল প্রশ্নের জন্য প্রস্তুতি নিতে পারেন। 
  • যদি আপনাকে নিয়োগ দেয়া হয়, তবে আপনি কি কি কোর্স পড়াতে চান বা পড়াতে পারবেন - এটাও একটা খুব কমন প্রশ্ন। 
  • সব প্রশ্নের উত্তর সংক্ষেপে, গুছিয়ে দেয়ার চেষ্টা করবেন। একজন প্রশ্ন করলো, তো আপনি ৫-৬ মিনিট ধরে একাই কথা বলে যাচ্ছেন - সেটা মোটেও ঠিক না।  চেষ্টা করবেন ২-৩ মিনিটের মধ্যে উত্তর দিয়ে দরকার হলে ডিসকাস করবেন - সার্চ কমিটি আরো ডিটেলস এ ব্যাপারে জানতে চান কিনা, জিজ্ঞেস করে নিতে পারেন।   
  • হাসি মুখে, যতটুকু সম্ভব রোবটের মতো না হয়ে উত্তর দিবেন।  মনে রাখবেন, সার্চ কমিটি আপনাকে তাঁদের কলিগ করবেন কিনা - মাথার পেছনে এই প্রশ্ন সব সময় রেখেছেন। সুতরাং, যতটুকু ফ্রেন্ডলি ভাবে উত্তর দিবেন। 
  • কোনো প্রশ্ন না বুঝলে, বিনীত ভাবে জিজ্ঞেস করাতে কোনো দোষ নেই। সার্চ কমিটিতে অনেকে দেশি মানুষ থাকেন, সবার কথার উচ্চারণ, বলার ধরন, গতি এক না - কাজেই কারো কথা না বুঝলে, 'দুঃখিত, আপনার কথা ঠিক ধরতে পারিনাই, আরেকবার বলবেন কি?" -  জিজ্ঞেস করে নিতেই পারেন। 
  • আপনি ক্লাসে শুধু পড়াবেনই না - ছাত্র-ছাত্রীদের কাছ থেকেও শিখতে চান, তাদের কাছ থেকে ফিডব্যাক নিয়ে নিজের পড়ানোর উন্নতি করতে চান, আপনি বিশ্বাস করেন শিক্ষাটা দ্বিমুখী -- এই কথাটা অনেকেই খুব পছন্দ করে দেখেছি। বলতে পারেন। 
  • ইউনিভার্সিটি, ডিপার্টমেন্ট ইত্যাদি সম্পর্কে আগেই জেনে রাখবেন।  ইন্টারভিউয়ের শেষের দিকে আপনার কোনো প্রশ্ন আছে কিনা - এটা জিজ্ঞেস করবেই।  তখন "না, আমার কোনো প্রশ্ন নাই" - বলাটা খুবই নেগেটিভ। তখন আপনি তাদের ইউনিভার্সিটি; ক্লাসে স্টুডেন্ট সংখ্যা কেমন; কোর্স লোড কি;  গবেষণা, পড়ানো, আর সার্ভিস - ইত্যাদির পার্সেন্টেজ কেমন ইত্যাদি জিজ্ঞেস করতে পারেন। 



ধাপ ৩: অন-সাইট ইন্টারভিউ, ক্যাম্পাস ভিসিট :
আপনার স্কাইপ বা জুম ইন্টারভিউ ভালো হলে, আপনি শর্ট লিস্টেড হলে ধাপ ৩ -এর জন্য ডাক পাবেন। ধাপ ৩ এ মূলত আপনি ওদের ক্যাম্পাসে মোটামুটি ৫-৬ ঘন্টার জন্য যাবেন। এই ধাপে সাধারণত আপনাকে একটা টিচিং আর আরেকটা রিসার্চ লেকচার দিতে হবে। লেকচারের বিষয় সচরাচর আপনি নিজেই ঠিক করতে পারবেন। তবে কিছু ক্ষেত্রে, যাতে তুলনা করতে সুবিধা হয়, সার্চ কমিটি আপনাকে একটা বিশেষ বিষয়ের উপর ছাত্র-ছাত্রীদেরকে একটা ৩০-৪০ মিনিটের টিচিং লেকচার দিতে বলতে পারে।  তবে, রিসার্চ লেকচার আপনি আপনার কাজের উপর দিতে পারবেন।

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

যা করা উচিত:

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




শেষ ধাপ, চাকরির অফার:

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

যা করা উচিত:

  • অবশ্যই বেতন নিয়ে নিগোশিয়েট করবেন।  আমরা বাংলাদেশিরা একটু বেশি লজ্জা পাই।  লজ্জা পাবেন না।  ধরে নিন, আপনি কারো এজেন্ট হয়ে কাজ করছেন।  দরকার হলে, সেটা চিন্তা করেই বেতন নিয়ে নিগোশিয়েট করবেন।  আপনি বেশি চাইলে, আর যাই হোক, আপনার চাকরির অফার চলে যাবে না।  বড়জোর, "এই বেতন চাইলেও আমরা দিতে পারছি না" - টাইপ কিছু বলে আপনাকে থামাবে।   
  • স্টার্ট-আপ ফান্ড অবশ্যই আলাপ করে নিবেন।  আপনার কাছ থেকে হয়তো একটা বাজেট চাইতে পারে, সেটা দেয়ার জন্য প্ৰয়োজনে সময় নিবেন।  কিন্তু অবশ্যই চেষ্টা করবেন টাকার পরিমান বাড়িয়ে নিতে।  পরবর্তীতে কম্পিউটার কেনা, ছাত্র-ছাত্রীদের বেতন দেয়া, কনফারেন্সে রেজিস্ট্রেশন, যাওয়ার খরচ হয়তো আপনাকে এই ফান্ড থেকেই দিতে হবে যতদিন আপনি বাইরে থেকে নিজে কোনো ফান্ড আনতে না পারছেন।  কাজেই ....
  • ইমিগ্রেশন'র ব্যাপারে খোঁজ নিন। ওরা স্পনসর করবে কিনা, করলে কবে, কতদিনের মধ্যে শুরু করবে ইত্যাদি বিষয়ে নিশ্চিত হয়ে নিবেন। 
  • হেলথ ইন্সুরেন্স, রিটায়ারমেন্ট ম্যাচিং প্ল্যান - ইত্যাদি সুযোগ সুবিধা সাধারণ আগে থেকেই ফিক্সড থাকে।  আপনাকে কাগজপত্র পাঠিয়ে দিবে। দেখে নিন।  দরকার হলে অন্যদের সাথে পরামর্শ করুন। 
  • অফার একসেপ্ট করার আগে, ইউনিভার্সিটি আশেপাশের থাকার পরিবেশ, আপনার বাচ্চা থাকলে স্কুলের রেটিং, সিটি ট্যাক্স আছে কিনা, বাঙালি কমিউনিটি, দোকান, (যদি আপনি ধার্মিক হন)  মসজিদ/মন্দির আছে কিনা ইত্যাদির খোঁজ নিন। সবচেয়ে ভালো হয়, আপনার ভবিষ্যত ডিপার্টমেন্টের কলিগদের সাথে কথা বলে নিন।  চেষ্টা করুন বুঝতে, তাঁরা আসলেই এইখানে কাজ করে খুশি কিনা। 

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



কাজের জায়গায় ভুল থেকে শেখা: regex 'র একটা খুব কমন বিষয় যেটা এতদিন ভুল জানতাম

কাজের জায়গায় ভুল থেকে শেখা: regex 'র একটা খুব কমন বিষয় যেটা এতদিন ভুল জানতাম  ৩ ফেব্রুয়ারি, শনিবার, ২০২৪ রেগুলার এক্সপ্রেশন (Regular Exp...