আবহাওয়া দারুণ ভালো, অথচ আপনি এক ঘণ্টা ক্লাসরুমে কাটানোর কথা ভেবে বিশেষ আগ্রহ বোধ করছেন না। বিরক্ত হয়ে আপনি ক্লাসরুমে ঢোকেন, আর সেখানে ব্ল্যাকবোর্ডে চোখে পড়ে অদ্ভুতভাবে মন ভরিয়ে দেওয়া একটি ত্রিভুজ। গণিতের শিক্ষক আসার জন্য অপেক্ষা করতে করতে আপনি ত্রিভুজটির কিছু প্যাটার্ন চোখে পড়া থামাতে পারেন না: একেবারে বাইরের মানগুলো সবই এক, প্রতিটি পরের সারিতে তার আগের সারির চেয়ে একটি মান বেশি, আর ত্রিভুজটি প্রতিসম। অদ্ভুত!
আপনি বসতে না বসতেই আপনার শিক্ষক ঘরে ঢোকেন এবং ব্যাখ্যা করেন যে এই ত্রিভুজটিই বিখ্যাত প্যাসকেলের ত্রিভুজ।
পরের এক ঘণ্টায় আপনার শিক্ষক এই ত্রিভুজের ভেতরে লুকিয়ে থাকা কিছু চমকপ্রদ বিষয় তুলে ধরেন:
শিক্ষক আপনার ও আপনার সহপাঠীদের কাছে অনুরোধ করেন, এই ত্রিভুজের আরও ব্যবহার খুঁজে দেখতে, এবং আশ্বাস দেন যে এমন ব্যবহার আরও অনেক আছে! ঠিক তখনই স্কুলের ঘণ্টা বেজে ওঠে। আপনি বুঝতে পারেন, গত এক ঘণ্টা ধরে আপনি প্যাসকেলের ত্রিভুজ সম্পর্কে শিখতে গিয়ে পুরোপুরি মগ্ন ছিলেন। আপনি দ্রুত ব্যাগ থেকে ল্যাপটপ বের করেন এবং বাইরে চলে যান, রোদের আলো আর প্যাসকেলের ত্রিভুজের বিস্ময়, দুটোই উপভোগ করার প্রস্তুতি নিয়ে।
আপনার কাজ হলো প্যাসকেলের ত্রিভুজের প্রথম N সারি আউটপুট করা।
প্যাসকেলের ত্রিভুজ হলো ধনাত্মক ইন্টিজারের একটি ত্রিভুজাকার অ্যারে।
প্যাসকেলের ত্রিভুজে একটি সারিতে থাকা মানের সংখ্যা তার সারি নম্বরের সমান (যা এক থেকে শুরু হয়)। তাই প্রথম সারিতে একটি মান থাকে, দ্বিতীয় সারিতে দুটি মান থাকে, আর এভাবেই চলতে থাকে।
প্রথম (সবচেয়ে উপরের) সারিতে একটি মাত্র মান থাকে: 1।
পরের সারিগুলোর মান হিসাব করা হয় আগের সারিতে বর্তমান অবস্থানের ঠিক ডানে ও বামে থাকা সংখ্যাগুলো যোগ করে।
আগের সারিতে বর্তমান অবস্থানের বামে বা ডানে কোনো মান না থাকলে (যা কেবল একেবারে বামের ও একেবারে ডানের অবস্থানের ক্ষেত্রেই ঘটে), ওই অবস্থানের মান শূন্য ধরে নিন (অর্থাৎ যোগ করার সময় সেটি কার্যত "উপেক্ষা" করা হয়)।
চলুন প্যাসকেলের ত্রিভুজের প্রথম ৫টি সারি দেখি:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
সবচেয়ে উপরের সারিতে একটি মান থাকে, সেটি 1।
একেবারে বামের ও একেবারে ডানের মানগুলোর বিবেচনা করার জন্য আগের সারিতে কেবল একটি অবস্থান থাকে, যা যথাক্রমে তাদের ডানের ও বামের অবস্থান।
সবচেয়ে উপরের মানটি 1 হওয়ায় এ থেকে বোঝা যায়, একেবারে বামের ও একেবারে ডানের সব মানও 1।
বাকি মানগুলোর প্রতিটির ক্ষেত্রে দুটি অবস্থান বিবেচনা করতে হয়।
যেমন, পঞ্চম সারির (1 4 6 4 1) মাঝের মানটি 6, কারণ আগের সারিতে তার বামে ও ডানে থাকা মান দুটি 3 ও 3:
এই অনুশীলনীটি লুপের বদলে recursion ব্যবহার করে সম্পন্ন করার জন্য তৈরি করা হয়েছে। রিকার্সিভ ফাংশন হলো এমন একটি ফাংশন যা নিজেকেই কল করে, আর যে সমস্যাগুলো নিজেদের ভিত্তিতেই সংজ্ঞায়িত, সেগুলো সমাধানে এটি কাজে লাগে। অসীম রিকার্সন এড়াতে (আরও নির্দিষ্ট করে বললে, স্ট্যাক ওভারফ্লো এড়াতে) "বেস কেস" নামের একটি কৌশল ব্যবহার করা হয়। বেস কেসে পৌঁছে গেলে রিকার্সিভ নয় এমন একটি মান রিটার্ন করা হয়, যার ফলে আগের ফাংশন কলটিও নিজের কাজ শেষ করে মান রিটার্ন করতে পারে; এভাবে স্ট্যাকের নিচের দিকে ছড়িয়ে পড়ে শেষে প্রথম ফাংশন কলটি উত্তর রিটার্ন করে। ৫!-এর (অর্থাৎ ৫ * ৪ * ৩ * ২ * ১) উত্তর বের করতে আমরা এভাবে একটি রিকার্সিভ ফাংশন লিখতে পারি:
def factorial(number):
if number <= 1: # base case
return 1
return number * factorial(number - 1) # recursive case
print(factorial(5)) # returns 120
সবশেষে মনে রাখা দরকার, Python রিকার্সিভ কল কতবার করা যাবে তা সীমিত রাখে (ডিফল্টভাবে ১০০০ বার) এবং টেইল রিকার্সন-এর জন্য অপটিমাইজ করে না।
কখনো কখনো এক্সেপশন রেইজ করা প্রয়োজন হয়। এমন করার সময় সবসময় একটি অর্থপূর্ণ এরর মেসেজ দিতে হবে, যাতে বোঝা যায় এররটির উৎস কী। এতে আপনার কোড আরও পড়ার উপযোগী হয় এবং ডিবাগিংয়ে অনেক সহায়তা করে। যেসব ক্ষেত্রে আপনি জানেন যে এররের উৎস নির্দিষ্ট কোনো টাইপ হবে, সেখানে আপনি বিল্ট-ইন এরর টাইপ-এর একটি রেইজ করা বেছে নিতে পারেন, তবে তবুও একটি অর্থপূর্ণ মেসেজ দিতে হবে।
এই নির্দিষ্ট অনুশীলনীতে rows() ফাংশনে ঋণাত্মক সংখ্যা পাঠানো হলে রেইজ স্টেটমেন্ট ব্যবহার করে একাধিক ValueErrors "থ্রো" করতে হবে।
টেস্ট কেবল তখনই পাস করবে, যখন আপনি exception raise করবেন এবং তার সঙ্গে একটি মেসেজও দেবেন।
মেসেজসহ একটি ValueError রেইজ করতে, মেসেজটি exception টাইপের আর্গুমেন্ট হিসেবে লিখুন:
# if the rows function is passed a negative number.
raise ValueError("number of rows is negative")
Exercism-এ সাইন আপ করুন, Python ট্র্যাকের 17টি কনসেপ্ট146টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।