সরাসরি পর্বে যান
পর্ব ০২ · ৫৫-এর মধ্যে · মডিউল ১

কোডের আগে ভাবা — সমস্যা ভাঙা ও অ্যালগরিদম

Think Before You Code — Problem Solving & Algorithms, the Python Way

Taught in Bangla, this lesson builds problem-solving habits before Python code: the four pillars of computational thinking, algorithms as recipes, turning pseudocode into Python, dry runs with trace tables, edge cases and a first feel for which approach is faster.

এই পর্বে যা শিখবেন

  • একটি ঝাপসা কাজকে (যেমন “বিল ভাগ করো”) ছোট, নিখুঁত উপ-সমস্যায় ভাঙা
  • অ্যালগরিদম কাকে বলে, আর একটি ভালো অ্যালগরিদমের শর্তগুলো কী
  • বাংলায় pseudocode লিখে তা থেকে Python কোড চেনা, আর flowchart পড়া
  • Trace table দিয়ে হাতে প্রোগ্রাম চালানো এবং edge case খুঁজে বের করা
  • কোন পদ্ধতি দ্রুত তা অনুভবে বোঝা — একটি একটি করে খোঁজা বনাম অর্ধেক করে খোঁজা

১ · কম্পিউটার অনুমান করে না — ঠিক যা বলবেন, তাই করে

ধরুন আপনি ছোট ভাইকে বললেন, “দোকান থেকে কিছু ডিম নিয়ে আয়।” সে নিজেই বুঝে নেবে কয়টা আনতে হবে, ভাঙা ডিম নেবে না, দাম বেশি হলে ফোন করবে। মানুষ ফাঁকটুকু নিজের বুদ্ধি দিয়ে পূরণ করে।

কম্পিউটার তা পারে না। “কিছু ডিম” মানে কয়টা? দোকান বন্ধ থাকলে কী হবে? টাকা কম পড়লে? প্রতিটি প্রশ্নের উত্তর আগে থেকেই, পরিষ্কার করে বলে দিতে হয়। কম্পিউটার খুব দ্রুত, কখনো ক্লান্ত হয় না — কিন্তু সে শুধু নির্দেশ মানে, উদ্দেশ্য বোঝে না।

মূল ধারণা

প্রোগ্রামিংয়ের বেশিরভাগ কাজ টাইপ করা নয়, ভাবা। একটি ঝাপসা লক্ষ্য (“বিলটা ভাগ করে দাও”) থেকে নিখুঁত, ধাপে ধাপে সাজানো নির্দেশ বানানোর দক্ষতাকে বলে computational thinking. আর সেই নির্দেশের তালিকাটিই algorithm.

অনেকে ভাবেন, আগে ভাষার নিয়ম (syntax) মুখস্থ করতে হবে, তারপর সমস্যা সমাধান। আসলে উল্টো। নিয়ম কয়েক সপ্তাহে শেখা যায়, আর এখন AI-ও নিয়ম ভালোই জানে। কিন্তু কী করতে হবে, কোন ক্রমে, কোন পরিস্থিতিতে প্রোগ্রাম ভেঙে পড়বে — এই ভাবনা আপনাকেই করতে হয়। এজন্যই এই কোর্সে সেটআপ আর প্রথম প্রোগ্রামের আগেই এই পর্ব রাখা হয়েছে।

ঝাপসা লক্ষ্য থেকে চালানো যায় এমন প্রোগ্রাম

From a fuzzy goal to precise, runnable steps

  1. ঝাপসা লক্ষ্য"বিল ভাগ করো"মানুষের ভাষা
  2. নিখুঁত ধাপpseudocodeআপনার ভাবনা
  3. Python কোডtotal // peopleপ্রায় একই চেহারা
  4. যাচাইdry runহাতে মিলিয়ে দেখা
ছবি ২.১ — সবচেয়ে কঠিন ধাপটি প্রথম তীর: ঝাপসা থেকে নিখুঁত।

এখানেই Python-এর একটি বড় সুবিধা। Python-এর কোড পড়লে অনেকটা ইংরেজি বাক্যের মতো লাগে। অনেকে মজা করে Python-কে বলেন “চালানো যায় এমন pseudocode”. ফলে আপনার মাথার পরিকল্পনা আর আসল কোডের মধ্যে দূরত্ব কম — ভাবনা পরিষ্কার হলে কোড প্রায় নিজে থেকেই চলে আসে।

এই পর্বে কিছু Python কোড দেখবেন। প্রতিটি চিহ্ন এখনই বোঝার দরকার নেই। নিয়ম শেখা শুরু হবে পর্ব ০৪ থেকে। এখন শুধু খেয়াল করুন, পরিকল্পনার প্রতিটি ধাপ কোডের কোন লাইনে বসেছে।

২ · Computational thinking-এর চারটি স্তম্ভ

যেকোনো সমস্যা — সেটা ঢাকায় অফিস যাওয়ার বাসের পথ ঠিক করা হোক বা একটি দোকানের দিনের হিসাব — চারটি কৌশলে ভাবা যায়। এগুলো কোনো নির্দিষ্ট ভাষার নিয়ম নয়; Python, C, Excel, এমনকি খাতা-কলমেও একই কাজে লাগে।

🧩 ভেঙে ফেলা · Decomposition

বড় সমস্যাকে ছোট ছোট অংশে ভাগ করা, যাতে প্রতিটি অংশ আলাদাভাবে সমাধান করা যায়। মিরপুর থেকে মতিঝিল যাওয়া মানে: কাছের স্টপেজে হাঁটা, ঠিক বাসে ওঠা, কোথায় নামবেন জানা, বাকি পথ হাঁটা বা রিকশা।

decomposition

🔁 মিল খোঁজা · Pattern recognition

আগে সমাধান করা সমস্যার সাথে মিল দেখা। মিরপুর–মতিঝিল আর উত্তরা–গুলিস্তান, দুটোই “স্টপেজে যাও, বাসে ওঠো, নামো”। একবার পদ্ধতি বুঝলে নতুন রুটেও একই ছাঁচ চলে।

pattern recognition

🗺️ দরকারি অংশ রাখা · Abstraction

অপ্রয়োজনীয় খুঁটিনাটি বাদ দিয়ে শুধু যা দরকার তা রাখা। বাসের রুট-ম্যাপে রাস্তার দোকান বা গাছ থাকে না, থাকে শুধু স্টপেজ আর লাইন। মেট্রো রেলের ম্যাপও তাই।

abstraction

📋 ধাপ সাজানো · Algorithm

সমাধানটি এমনভাবে লেখা, যাতে যে কেউ (বা কম্পিউটার) একই ধাপ মেনে একই ফল পায়: “১০ নম্বর বাসে উঠুন, ৯টা স্টপেজ পরে মতিঝিলে নামুন।”

algorithm

তিনটি বাস্তব উদাহরণে চার স্তম্ভ

স্তম্ভরেস্তোরাঁর বিল ভাগমুদি দোকানের দিনশেষের স্টকসব বিষয়ে পাস কি না
ভেঙে ফেলামোট বিল, কতজন, কীভাবে ভাগ, রাউন্ড করাসকালের মাল, বিক্রি, নতুন আসা, বাকিনম্বর নেওয়া, প্রতিটি যাচাই, ফল জানানো
মিল খোঁজাপিকনিকের চাঁদা ভাগও একই সমস্যাপ্রতিটি পণ্যের হিসাব একই নিয়মেপ্রতিটি বিষয়ে একই প্রশ্ন: ৩৩-এর কম?
দরকারি অংশকে কী খেয়েছে দরকার নেই (সমান ভাগ হলে)পণ্যের রং-মোড়ক নয়, শুধু সংখ্যাশিক্ষার্থীর ঠিকানা নয়, শুধু নম্বর
ধাপ সাজানোমোট ÷ জন, বাকি টাকা কয়েকজনে ১ টাকা করেবাকি = সকাল + নতুন − বিক্রিএকটিও ৩৩-এর কম হলে ফেল, নইলে পাস

এবার সবচেয়ে গুরুত্বপূর্ণ স্তম্ভটি — ভেঙে ফেলা — ধাপে ধাপে দেখি। চার বন্ধু ধানমন্ডির একটি রেস্তোরাঁয় খেলেন। বিল এলো। কেউ একজন বলল, “ভাগ করে দে।” শুনতে সহজ, কিন্তু প্রোগ্রাম লিখতে গেলে বোঝা যায় এর ভেতরে কতগুলো আলাদা প্রশ্ন লুকিয়ে আছে। “পরে” চাপুন:

  1. লক্ষ্যবিল ভাগঝাপসা
  2. মোট কত?totalভ্যাট, টিপস
  3. কতজন?peopleশূন্য হলে?
  4. কোন নিয়মে?সমান ভাগনীতি ঠিক করা
  5. রাউন্ড৳ পূর্ণ সংখ্যাবাকি টাকা
  6. জানানোকে কতমিলিয়ে দেখা
  1. শুরু — একটি ঝাপসা লক্ষ্য। “বিল ভাগ করো।” মানুষ হলে বুঝে নিত। কিন্তু প্রোগ্রামের কাছে এটি একটি প্রশ্নের স্তূপ। ভাঙার নিয়ম একটাই: প্রতিটি টুকরো এত ছোট করুন, যাতে তার সমাধান এক-দুই লাইনে বলা যায়।
  2. উপ-সমস্যা ১ — মোট টাকা কত? খাবারের দাম যোগ করতে হবে। রেস্তোরাঁ ভ্যাট বা সার্ভিস চার্জ যোগ করলে সেটাও। ধরুন সব মিলিয়ে ১,০০০ টাকা। এটি আমাদের প্রথম input.
  3. উপ-সমস্যা ২ — কতজন দেবেন? এখানে ৩ জন (একজন আগেই চলে গেছেন)। এখনই একটি প্রশ্ন জাগা উচিত: সংখ্যাটি ভুল করে ০ দিলে কী হবে? শূন্য দিয়ে ভাগ করা যায় না। এমন বিশেষ পরিস্থিতির নাম edge case; অংশ ৬-এ বিস্তারিত দেখব।
  4. উপ-সমস্যা ৩ — কোন নিয়মে ভাগ? সমান ভাগ, নাকি যে যা খেয়েছে? এটি গণিতের প্রশ্ন নয়, নীতির প্রশ্ন — প্রোগ্রাম লেখার আগেই মানুষকে ঠিক করতে হয়। আমরা সমান ভাগ বেছে নিলাম। খেয়াল করুন: ভেঙে ফেলার সময়ই এমন লুকানো সিদ্ধান্ত বেরিয়ে আসে।
  5. উপ-সমস্যা ৪ — টাকায় রাউন্ড করা। ১,০০০ ÷ ৩ = ৩৩৩.৩৩… কিন্তু bKash-এ ৩৩ পয়সা পাঠানো যায় না, আর ৩৩৩ করে দিলে মোট হয় ৯৯৯ — ১ টাকা কম! সমাধান: সবাই ৩৩৩ দেবেন, বাকি ১ টাকা একজন বেশি দেবেন। অর্থাৎ ৩৩৪ + ৩৩৩ + ৩৩৩ = ১,০০০.
  6. উপ-সমস্যা ৫ — ফল জানানো ও মিলিয়ে দেখা। কে কত দেবেন তা দেখানো, আর শেষে যোগ করে নিশ্চিত হওয়া যে মোট ঠিক ১,০০০ টাকাই হয়েছে। এখন প্রতিটি টুকরো এত ছোট যে প্রতিটির জন্য Python-এ এক-দুই লাইনই যথেষ্ট — অংশ ৬-এ ঠিক এই কোডটিই চালাব।

বিয়ের আয়োজনের কথা ভাবুন। “বিয়ে আয়োজন করো” — এভাবে কেউ কাজ শুরু করে না। ভাগ হয়: কমিউনিটি সেন্টার, বাবুর্চি, কার্ড, অতিথির তালিকা, গাড়ি। প্রতিটি দায়িত্ব একজনের হাতে যায়। বড় সফটওয়্যারও ঠিক এভাবে তৈরি হয় — প্রতিটি টুকরো একটি function বা একটি ফাইল, যা পরে জোড়া লাগে।

৩ · অ্যালগরিদম আসলে কী — একটি রেসিপি

মায়ের খিচুড়ির রেসিপি মনে করুন: চাল-ডাল ধুয়ে নিন, পেঁয়াজ ভাজুন, মসলা দিন, চাল-ডাল দিয়ে নাড়ুন, পানি দিন, ২০ মিনিট রান্না করুন। এখানে আছে উপকরণ (input), ক্রমানুসারে ধাপ, আর শেষে একটি ফল (output) — খিচুড়ি। অ্যালগরিদম ঠিক এটাই, শুধু নির্দেশগুলো আরও নিখুঁত।

“লবণ পরিমাণমতো” লেখা রেসিপি মানুষের জন্য ঠিক আছে, কিন্তু কম্পিউটারের জন্য নয়। কম্পিউটারের রেসিপিতে লিখতে হবে “১ চা-চামচ লবণ”। এজন্য একটি ভালো অ্যালগরিদমের কয়েকটি শর্ত আছে:

শর্তঅর্থরেসিপিতে উদাহরণ
সসীম (finite)নির্দিষ্ট সংখ্যক ধাপের পর অবশ্যই শেষ হবে“২০ মিনিট রান্না করুন” — “যতক্ষণ খুশি” নয়
নিখুঁত (precise)প্রতিটি ধাপের একটিই অর্থ, দ্বিধার সুযোগ নেই“১ চা-চামচ লবণ” — “পরিমাণমতো” নয়
ইনপুটশুরুতে কী কী লাগবে, স্পষ্ট বলাচাল, ডাল, পেঁয়াজ, পানি
আউটপুটশেষে কী পাওয়া যাবে, স্পষ্ট বলাএক হাঁড়ি খিচুড়ি
করা সম্ভব (effective)প্রতিটি ধাপ বাস্তবে করা যায়“চাল ধুয়ে নিন” — “চাল নিজে নিজে সেদ্ধ হোক” নয়

একটি ছোট অ্যালগরিদম: পাঁচ দোকানের মধ্যে সবচেয়ে সস্তা

আপনি এক কেজি চাল কিনবেন। পাড়ার পাঁচটি দোকানে দাম জেনেছেন: ৭৮, ৭৪, ৮০, ৭৫ আর ৭৪ টাকা। মানুষ এক নজরেই বলে দেবে “৭৪”. কিন্তু চোখ আসলে কী করল? সে প্রতিটি দাম দেখেছে আর এখন পর্যন্ত সবচেয়ে কমটি মনে রেখেছে। এই অদৃশ্য কাজটিকেই শব্দে লিখি:

  1. প্রথম দোকানের দামটিকে “এখন পর্যন্ত সবচেয়ে সস্তা” ধরে নিন।
  2. বাকি প্রতিটি দোকানের দাম একে একে দেখুন।
  3. কোনো দাম মনে রাখা দামের চেয়ে কম হলে, সেটিকে নতুন “সবচেয়ে সস্তা” হিসেবে মনে রাখুন।
  4. সব দেখা শেষ হলে, মনে রাখা দামটিই উত্তর।

এটি সসীম (পাঁচটি দাম দেখলেই শেষ), নিখুঁত (“কম” মানে কঠোরভাবে কম), ইনপুট (দামের তালিকা) আর আউটপুট (সবচেয়ে কম দাম) — সব শর্তই পূরণ করে। একটি প্রশ্ন রেখে যাই: দুটি দোকানে একই ৭৪ টাকা — আমাদের নিয়ম কোনটির নাম বলবে? উত্তর পাবেন পরের অংশের কোডে।

“Algorithm” শব্দটি এসেছে নবম শতকের বাগদাদের গণিতবিদ মুহাম্মদ ইবনে মুসা আল-খোয়ারিজমি-র নাম থেকে। তাঁর একটি বইয়ের লাতিন অনুবাদের শিরোনাম শুরু হয় “Algoritmi de numero Indorum” দিয়ে — অর্থাৎ “ভারতীয় সংখ্যা নিয়ে আল-খোয়ারিজমি”. আর লেখা অ্যালগরিদমের সবচেয়ে বিখ্যাত পুরোনো উদাহরণগুলোর একটি হলো ইউক্লিডের গসাগু বের করার পদ্ধতি, প্রায় ২,৩০০ বছর আগের। অর্থাৎ অ্যালগরিদম কম্পিউটারের চেয়ে অনেক পুরোনো।

৪ · Pseudocode থেকে Python — চেহারায় প্রায় এক

Pseudocode মানে “নকল কোড” — প্রোগ্রামের মতো সাজানো, কিন্তু কোনো ভাষার কঠিন নিয়ম ছাড়া, নিজের ভাষায় লেখা পরিকল্পনা। এটি বাংলায়, ইংরেজিতে বা দুটো মিশিয়ে লেখা যায়। লক্ষ্য একটাই: কোড লেখার আগে যুক্তিটা পরিষ্কার করা।

“সব বিষয়ে পাস করেছে কি না” সমস্যাটি নিন। নিয়ম: কোনো একটি বিষয়েও ৩৩-এর কম পেলে ফেল। বাঁ পাশে pseudocode, ডান পাশে একই যুক্তির Python:

📝 Pseudocode (বাংলায়)

নম্বরের তালিকা নাও
পাস = হ্যাঁ ধরে নাও
প্রতিটি নম্বরের জন্য:
    যদি নম্বর ৩৩-এর কম হয়:
        পাস = না
যদি পাস হ্যাঁ হয়:
    বলো "পাস"
নইলে:
    বলো "ফেল"

🐍 Python

marks = [78, 45, 33, 90]
passed = True
for m in marks:
    if m < 33:
        passed = False
if passed:
    print("পাস")
else:
    print("ফেল")

প্রায় লাইনে লাইনে মিল! “প্রতিটি নম্বরের জন্য” হয়েছে for m in marks, “যদি” হয়েছে if, “নইলে” হয়েছে else. ভেতরের ধাপগুলো ডানদিকে সরানো (indentation) — pseudocode-এ এটা শুধু দেখতে সুন্দর করার জন্য, কিন্তু Python-এ এটাই নিয়ম: কোন লাইন কোন শর্তের ভেতরে, তা ঠিক হয় ফাঁকা জায়গা দিয়ে। for আসবে পর্ব ১২-এ, if পর্ব ১১-এ, আর এমন একটি তালিকা — list — পর্ব ১৪-এ।

এবার আগের অংশের “সবচেয়ে সস্তা দোকান” অ্যালগরিদমটি আসল Python-এ চালিয়ে দেখুন। কমেন্টে (# দিয়ে শুরু লাইন) পরিকল্পনার ধাপগুলো লেখা আছে:

# Price of 1 kg rice at 5 shops (in taka)
shops = ["করিম স্টোর", "মিনা বাজার", "রহিম ট্রেডার্স", "স্বপ্ন", "পাড়ার মুদি"]
prices = [78, 74, 80, 75, 74]

# Step 1: assume the first shop is the cheapest
best = 0
# Step 2: compare every other shop with the current best
for i in range(1, len(prices)):
    if prices[i] < prices[best]:   # strictly cheaper only
        best = i
# Step 3: report the answer
print("Cheapest:", shops[best], "-", prices[best], "taka")
print("Check with min():", min(prices))

আউটপুট: Cheapest: মিনা বাজার - 74 taka আর Check with min(): 74. খেয়াল করুন, “পাড়ার মুদি”-তেও দাম ৭৪, কিন্তু উত্তর এসেছে মিনা বাজার। কারণ শর্তে আছে < (কঠোরভাবে কম) — সমান দাম পেলে আগের দোকানটিই থেকে যায়। আপনি <= লিখলে উত্তর হতো “পাড়ার মুদি”. ছোট একটি চিহ্ন, কিন্তু ভিন্ন সিদ্ধান্ত — তাই পরিকল্পনাতেই ঠিক করতে হয়, সমান হলে কী হবে। শেষ লাইনে Python-এর তৈরি min() দিয়ে উত্তরটি মিলিয়েও দেখা হয়েছে। আর বাংলা দোকানের নামও ঠিকঠাক ছাপা হয়েছে, কারণ Python 3-এর string শুরু থেকেই Unicode.

Flowchart — ভাবনার ছবি

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

“সব বিষয়ে পাস?” — flowchart

Oval = start/end · Parallelogram = input/output · Diamond = decision · Rectangle = process

  1. শুরুডিম্বাকার
  2. নম্বর নাওইনপুট
  3. কোনোটি < ৩৩?সিদ্ধান্ত
  4. হ্যাঁ → “ফেল”
    না → “পাস”
    আউটপুট
  5. শেষডিম্বাকার
ছবি ২.২ — হীরার আকারের বাক্স (সিদ্ধান্ত) থেকেই পথ দুই ভাগ হয়; কোডে এটিই if/else.
C/C++ জানলে

ভাবনার অংশ — ভেঙে ফেলা, অ্যালগরিদম, dry run — যেকোনো ভাষায় হুবহু এক। পার্থক্য কোডে: C-তে array-র আকার, ভ্যারিয়েবলের টাইপ আর int-এর সীমা নিজেকে সামলাতে হয়, Python-এ list নিজে বাড়ে আর পূর্ণসংখ্যা যত বড় খুশি হতে পারে। তাই Python-এর pseudocode-এর সাথে মিল বেশি। loop invariant আর flowchart-এর গভীর আলোচনা পাবেন C কোর্সের কম্পিউটেশনাল থিংকিং পর্বে।

৫ · হাতে চালিয়ে দেখা — dry run আর trace table

কোড লিখে “Run” চাপা সহজ। কিন্তু উত্তর ভুল এলে কোথায় ভুল, বুঝবেন কীভাবে? আর উত্তর ঠিক এলেও, সেটা কি সব ইনপুটে ঠিক? এর পুরোনো, নির্ভরযোগ্য উপায় হলো dry run — কম্পিউটার ছাড়া, খাতা-কলমে নিজেই কম্পিউটার হয়ে প্রতিটি লাইন চালানো।

Dry run-এর হাতিয়ার একটি trace table: প্রতিটি variable-এর জন্য একটি কলাম, আর প্রতিটি ধাপে একটি সারি। মান বদলালেই নতুন সারিতে লিখুন। নিচে পাঁচ বিষয়ের নম্বর থেকে সর্বোচ্চ নম্বর খোঁজার কোড। “পরে” চাপুন আর নিচের খাতায় trace table কীভাবে ভরে উঠছে দেখুন:

1marks = [72, 85, 64, 91, 78]2best = marks[0]3for m in marks:4    if m > best:5        best = m6print(best)
ভ্যারিয়েবলের মান
m
m > best?
best

        
  1. শুরু। লাইন ১–২ চলল: পাঁচটি নম্বরের তালিকা তৈরি হলো, আর প্রথম নম্বরটিকে (72) “এখন পর্যন্ত সর্বোচ্চ” ধরে best-এ রাখা হলো। খাতায় প্রথম সারি লিখুন।
  2. প্রথম পাক: m = 72. 72 কি 72-এর চেয়ে বড়? না (সমান)। তাই লাইন ৫ চলল না, best একই থাকল। অনেকে এই ধাপ বাদ দেন, কিন্তু dry run-এ প্রতিটি পাক লিখতে হয় — ভুল প্রায়ই লুকিয়ে থাকে “তুচ্ছ” ধাপে।
  3. দ্বিতীয় পাক: m = 85. 85 > 72? হ্যাঁ! লাইন ৫ চলল, best হলো 85. খাতায় তীর (←) দিয়ে চিহ্ন দিন — মান বদলেছে।
  4. তৃতীয় পাক: m = 64. 64 > 85? না। কিছু বদলাল না।
  5. চতুর্থ পাক: m = 91. 91 > 85? হ্যাঁ — best হলো 91.
  6. পঞ্চম পাক: m = 78. 78 > 91? না। তালিকা শেষ, লুপও শেষ।
  7. লাইন ৬: ফল ছাপা হলো — 91. হাতে চালানো উত্তর আর আসল উত্তর মিলে গেল। এবার নিজেকে প্রশ্ন করুন: তালিকা খালি হলে লাইন ২-এ marks[0] কী করবে? সব নম্বর ঋণাত্মক হলে? এই প্রশ্নগুলোই পরের অংশের বিষয়।
কেন dry run এত মূল্যবান

Dry run আপনাকে বাধ্য করে প্রতিটি লাইনের আসল অর্থ বুঝতে — “মনে হয় এটা এমন করবে” নয়। এটি কাজে লাগে তিন জায়গায়: নিজের অ্যালগরিদম যাচাইয়ে, অন্যের (বা AI-এর) কোড বুঝতে, আর পরীক্ষায় “আউটপুট কী হবে?” প্রশ্নে। এই কোর্সের পর্ব ৫২ পুরোটাই এমন কোড-পড়ার অনুশীলন।

Debugging-এর মানসিকতা — একটি ঝলক

প্রোগ্রামের ভুলকে বলে bug, আর ভুল খুঁজে ঠিক করার কাজকে debugging. নতুনরা প্রায়ই ভুল উত্তর দেখে এলোমেলোভাবে কোড বদলাতে থাকেন, “এবার হয়তো চলবে”. অভিজ্ঞরা করেন উল্টো: আগে অনুমান (“আমার মনে হয় লুপ একবার কম চলছে”), তারপর প্রমাণ (dry run বা print() দিয়ে মান দেখা), তারপর ঠিক করা। এটি একরকম গোয়েন্দাগিরি। Python-এর debugger আর logging নিয়ে বিস্তারিত পাবেন পর্ব ৪০-এ; আজকের trace table-ই তার ভিত্তি।

৬ · Edge case — যেখানে প্রোগ্রাম ভেঙে পড়ে

সাধারণ ইনপুটে প্রায় সব প্রোগ্রামই ঠিক চলে। বাগ লুকিয়ে থাকে কিনারায় — যেমন খালি তালিকা, শূন্য, ঋণাত্মক সংখ্যা, অনেক বড় সংখ্যা, অদ্ভুত নাম। এগুলোই edge case. পেশাদাররা কোড লেখার আগেই এমন একটি তালিকা বানান। চলুন বিল-ভাগের সমস্যায় edge case শিকার করি:

সাধারণ ইনপুটমোট ১২০০, জন ৪
1200 ÷ 4 = 300
প্রত্যেকে: 300, 300, 300, 300
মোট মিলল: 1200 ✓
ভাগ মেলে নামোট ১০০০, জন ৩
1000 ÷ 3 = 333.333…
শুধু 333 করে দিলে মোট = 999 ✗ (১ টাকা কম)
সমাধান: 334, 333, 333 → মোট 1000 ✓
শূন্য জনমোট ১০০০, জন ০
1000 ÷ 0 = ???
ZeroDivisionError  # প্রোগ্রাম থেমে যাবে
সমাধান: আগেই যাচাই — জন ০ বা কম হলে ভাগ নয়
ঋণাত্মক বা শূন্য বিলমোট −৫০০ বা ০
মোট = -500  # টাইপের ভুল? নাকি ফেরত টাকা?
প্রত্যেকে: -167, -167, -166
সিদ্ধান্ত লাগবে: ভুল বলে থামবেন, নাকি ফেরত হিসেবে ভাগ করবেন?
অনেক বড় সংখ্যাঅফিস পিকনিক, ২০০ জন
মোট = 12345678, জন = 200
Python-এ int যত বড় খুশি — overflow নেই
কিন্তু 200 জনের তালিকা দেখানো? সারাংশ দেখানোই ভালো
নাম নিয়ে ঝামেলাবাংলা নাম, একই নাম দুবার
names = ["তানিয়া", "রাফি", "রাফি"]
দুজন রাফি — কে কত দেবে আলাদা করবেন কীভাবে?
বাংলা নাম: Python 3-এ সমস্যা নেই, তবে সাজানোর ক্রম ভিন্ন হতে পারে
  1. সাধারণ ইনপুট — “সুখের পথ”। ১,২০০ টাকা ৪ জনে, প্রত্যেকে ৩০০. সবাই প্রথমে এটাই পরীক্ষা করে, আর এটা চললেই খুশি হয়ে যায়। কিন্তু এখান থেকে শুরু, শেষ নয়।
  2. ভাগ মেলে না। ১,০০০ ÷ ৩ দশমিকে যায়। শুধু ভাগফল নিলে ১ টাকা হারিয়ে যায় — দোকানদার তো ছাড়বে না! বাকি টাকা কে দেবেন, সেই নিয়ম অ্যালগরিদমেই থাকতে হবে।
  3. শূন্য জন। কেউ ভুল করে ০ দিলে Python ZeroDivisionError দিয়ে থেমে যাবে। ভালো অ্যালগরিদম ভাগ করার আগেই যাচাই করে। এমন ভুল সামলানোর পদ্ধতি (exception) আসবে পর্ব ২৪-এ।
  4. ঋণাত্মক বা শূন্য বিল। এখানে প্রোগ্রাম ভাঙে না, কিন্তু অর্থহীন উত্তর দেয়। এটি আসলে একটি নীতির প্রশ্ন — ভুল ইনপুট হিসেবে ফেরত দেবেন, নাকি “ফেরত টাকা” হিসেবে ভাগ করবেন? প্রোগ্রামার একা নয়, যিনি প্রোগ্রাম ব্যবহার করবেন তাঁর সাথে মিলে ঠিক করতে হয়।
  5. অনেক বড় সংখ্যা। C বা Java-তে পূর্ণসংখ্যার একটি সীমা থাকে, পার হলে মান উল্টাপাল্টা হয়ে যায় (overflow). Python-এর int-এর এমন সীমা নেই — একটি বড় স্বস্তি। তবে বড় ইনপুটে গতি আর আউটপুটের আকার নিয়েও ভাবতে হয়।
  6. নাম। একই নামের দুজন থাকলে শুধু নাম দিয়ে আলাদা করা যায় না — আলাদা পরিচয় (যেমন ফোন নম্বর) লাগে। বাংলা নাম Python 3 ঠিকঠাক ছাপে, কিন্তু বর্ণানুক্রমে সাজানো আর অক্ষর গোনায় সূক্ষ্ম ব্যাপার আছে (পর্ব ০৯-এ দেখবেন)। এই ছয়টি ধাপই আপনার edge case চেকলিস্ট।

এবার চেকলিস্ট মেনে লেখা বিল-ভাগের কোডটি চালিয়ে দেখুন। এখানে // মানে ভাগফলের পূর্ণসংখ্যা অংশ, আর % মানে ভাগশেষ — দুটোই আসবে পর্ব ০৭-এ। def দিয়ে একটি ফাংশন বানানো হয়েছে, যা শিখবেন পর্ব ১৩-এ।

# Split a restaurant bill fairly, in whole taka
def split_bill(total, people):
    if people <= 0:
        return None                  # edge case: nobody to pay
    base = total // people           # everyone pays at least this
    extra = total % people           # leftover taka
    # the first `extra` people pay 1 taka more
    return [base + 1] * extra + [base] * (people - extra)

print(split_bill(1200, 4))
print(split_bill(1000, 3))
print(split_bill(1000, 0))

shares = split_bill(1000, 3)
print("Total check:", sum(shares))

আউটপুট চার লাইনের: [300, 300, 300, 300], [334, 333, 333], None আর Total check: 1000. ১,০০০ ÷ ৩-এ ভাগফল ৩৩৩, ভাগশেষ ১ — তাই প্রথম একজন ৩৩৪ দিচ্ছেন। শূন্য জন দিলে প্রোগ্রাম ভেঙে না পড়ে None (“কোনো উত্তর নেই”) ফেরত দিচ্ছে। আর শেষ লাইনটি নিজেই একটি যাচাই: সবার ভাগ যোগ করলে মূল বিল ফিরে আসে কি না। প্রতিটি লাইন অংশ ২-এর এক-একটি উপ-সমস্যার উত্তর — ভেঙে ফেলা ঠিক হলে কোড এমন ছোটই হয়।

একটি সূক্ষ্ম edge case: “সব বিষয়ে পাস?” প্রোগ্রামে নম্বরের তালিকা খালি হলে কী হবে? লুপ একবারও চলবে না, passed থেকে যাবে True — অর্থাৎ কোনো পরীক্ষা না দিয়েই “পাস”! গণিতে একে বলে vacuous truth. Python-এর তৈরি all([])-ও True দেয়। এটি ভুল নয়, কিন্তু আপনার সমস্যায় এই আচরণ চান কি না, সেটা আগেই ভাবতে হবে।

৭ · কোনটি দ্রুত — ফোনের কন্টাক্ট লিস্ট থেকে শেখা

একই সমস্যার একাধিক সঠিক অ্যালগরিদম থাকতে পারে, কিন্তু সবগুলো সমান দ্রুত নয়। ফোনের কন্টাক্ট লিস্টে “Sabbir” খুঁজছেন। দুটি উপায়:

  • উপায় ক — একে একে দেখা (linear search): প্রথম নাম থেকে শুরু করে একটি একটি করে নিচে নামা। তালিকা সাজানো না থাকলেও চলে।
  • উপায় খ — মাঝখান থেকে অর্ধেক করা (binary search): তালিকা বর্ণানুক্রমে সাজানো, তাই মাঝখানে চোখ দিন। মাঝের নাম “M” হলে “S” নিশ্চয়ই পরের অর্ধেকে — আগের অর্ধেক পুরোটা বাদ। আবার মাঝখান, আবার অর্ধেক।

ক্লাসের ১৬ জন শিক্ষার্থীর রোল নম্বর ছোট থেকে বড় ক্রমে সাজানো। আমরা খুঁজছি রোল ৬৩. দুই পদ্ধতি পাশাপাশি চালাই — প্রতিটি ধাপে দুজনেই একবার করে একটি রোল দেখবে:

উপায় ক — একে একে (×× = দেখা হয়েছে, মেলেনি)

উপায় খ — অর্ধেক করে (-- = বাদ পড়েছে)

হিসাব
উপায় ক: কতবার দেখা
উপায় খ: মাঝের রোল
উপায় খ: বাকি কয়টি রোল
  1. শুরু। ১৬টি সাজানো রোল। দুই পদ্ধতিই এখনো কিছু দেখেনি। মনে রাখুন: উপায় খ কাজ করে শুধু সাজানো তালিকায়।
  2. ১ম দেখা। উপায় ক দেখল প্রথম রোল ০৩ — মেলেনি, বাদ গেল মাত্র একটি। উপায় খ দেখল মাঝের রোল ৩৪. ৬৩ তার চেয়ে বড়, আর তালিকা সাজানো — তাই ৩৪ ও তার বাঁয়ের সব (৮টি) একসাথে বাদ!
  3. ২য় দেখা। উপায় ক: ০৮, আবার একটি বাদ। উপায় খ: বাকি ৮টির মাঝে ৫৮. ৬৩ বড় — আরও ৪টি বাদ। বাকি মাত্র ৪টি: ৬৩, ৭০, ৭৭, ৮৫.
  4. ৩য় দেখা। উপায় ক: ১২. উপায় খ: বাকি চারটির মাঝে ৭০. ৬৩ ছোট — তাই ৭০ ও তার ডানের সব বাদ। বাকি একটিমাত্র রোল: ৬৩.
  5. ৪র্থ দেখা। উপায় খ শেষবার দেখল ৬৩ — পাওয়া গেছে! মাত্র ৪ বারে। উপায় ক তখনো ১৫-তে দাঁড়িয়ে।
  6. শেষ ফল। উপায় ক-কে ৬৩ পেতে ১৩ বার দেখতে হলো। ১৬টি রোলের যেকোনোটি উপায় খ-তে সর্বোচ্চ ৫ বারে পাওয়া যায় (১৬ → ৮ → ৪ → ২ → ১), আর উপায় ক-তে সবচেয়ে খারাপ ক্ষেত্রে ১৬ বার। তালিকা যত বড়, পার্থক্য তত বিশাল।
সাজানো তালিকায় কয়টি নামএকে একে (সবচেয়ে খারাপ ক্ষেত্রে)অর্ধেক করে (সবচেয়ে খারাপ ক্ষেত্রে)
১৬ (এক ক্লাসের রোল)১৬ বার৫ বার
৫০০ (ফোনের কন্টাক্ট)৫০০ বার৯ বার
১ লাখ (একটি বড় বিশ্ববিদ্যালয়ের সব রেজিস্ট্রেশন)১ লাখ বার১৭ বার
১০ লাখ১০ লাখ বার২০ বার

তালিকা দ্বিগুণ হলে একে একে খোঁজায় কাজও দ্বিগুণ হয়, কিন্তু অর্ধেক করে খোঁজায় লাগে মাত্র একটি বাড়তি ধাপ। কাজের পরিমাণ ইনপুটের আকারের সাথে কীভাবে বাড়ে — এই ভাবনার আনুষ্ঠানিক নাম Big-O notation: একে একে খোঁজা O(n), অর্ধেক করে খোঁজা O(log n). এখন শুধু অনুভূতিটুকু রাখুন; বিস্তারিত হিসাব, Python-এর bisect module আর কনটেস্টের কৌশল পাবেন পর্ব ৪৫-এ।

একটি সতর্কতা: binary search শুনতে সহজ, কিন্তু নির্ভুলভাবে লেখা কুখ্যাতভাবে কঠিন — সীমা এক ঘর এদিক-ওদিক হলেই লুপ আর থামে না, বা শেষ উপাদানটি বাদ পড়ে যায়। এমন ভুলকে বলে off-by-one error. AI-এর লেখা binary search-ও এই ভুল করতে পারে। তাই ১, ২ আর ৩ উপাদানের তালিকায়, আর তালিকার প্রথম ও শেষ উপাদান খুঁজে dry run করা বাধ্যতামূলক অভ্যাস করুন।

৮ · AI-এর যুগে — আগে পরিকল্পনা, পরে কোড

ChatGPT বা অন্য কোনো AI-কে “বিল ভাগের Python কোড দাও” বললে কয়েক সেকেন্ডে কোড চলে আসে। সমস্যা হলো, AI সাধারণত সরাসরি কোডে লাফ দেয়। সে ধরে নেয় সমান ভাগ, ধরে নেয় দশমিকে উত্তর দিলেই চলবে, আর শূন্য জনের কথা প্রায়ই ভাবে না। কোড দেখতে সুন্দর, চলেও — কিন্তু আপনার আসল সমস্যার উত্তর হয়তো নয়।

AI-এর কাছে কোডের আগে চান পরিকল্পনা।
পরিকল্পনা ঠিক হলে কোড যাচাই করা সহজ।

AI সাধারণত যেসব ভাবনা-ভুল করে

AI-এর ভুলউদাহরণকীভাবে ধরবেন
নিজে থেকে নীতি ধরে নেয়সমান ভাগ ধরে নিল, অথচ আপনি চেয়েছিলেন যে যা খেয়েছেশুরুতেই অনুমানগুলোর তালিকা চান
Edge case বাদ রাখেখালি তালিকায় marks[0] → IndexErrorনিজের edge case চেকলিস্ট দিয়ে চালান
রাউন্ডিং ভুলে যায়333.3333333333333 টাকাউত্তর যোগ করে মূল টাকা ফিরে আসে কি না দেখুন
সীমায় এক ঘর ভুলbinary search শেষ উপাদান খুঁজে পায় নাপ্রথম ও শেষ উপাদান দিয়ে dry run

কোড চাওয়ার আগে AI-কে নিচের মতো প্রশ্ন করুন। খেয়াল করুন, এখানে কোড চাওয়াই হয়নি — চাওয়া হয়েছে ভাবনা। কোড পরে চাইবেন, পরিকল্পনা আপনার পছন্দ হলে।

আমি Python শিখছি। একটা রেস্তোরাঁর বিল কয়েকজন বন্ধুর মধ্যে ভাগ করার প্রোগ্রাম বানাতে চাই। এখনই কোড দিও না। ১. সমস্যাটিকে ছোট ছোট উপ-সমস্যায় ভেঙে দেখাও। ২. তুমি কোন কোন বিষয় নিজে থেকে ধরে নিচ্ছ (যেমন সমান ভাগ কি না), তার তালিকা দাও — আমি ঠিক করে দেব। ৩. বাংলায় pseudocode লেখো, প্রতিটি ধাপ এক লাইনে। ৪. অন্তত ৬টি edge case বলো (শূন্য, ঋণাত্মক, ভাগ না মেলা, অনেক বড় সংখ্যা ইত্যাদি) আর প্রতিটিতে কী হওয়া উচিত। ৫. মোট 1000 টাকা, 3 জন — এই ইনপুটে তোমার pseudocode-এর একটি trace table দেখাও।

AI-এর দেওয়া অ্যালগরিদম হাতে পেলে — যাচাইয়ের চেকলিস্ট

পরীক্ষা ও ইন্টারভিউতে

বিশ্ববিদ্যালয়, চাকরি বা ইন্টারভিউর পরীক্ষায় এই ধরনের প্রশ্ন প্রায়ই আসে:

  • অ্যালগরিদম কী, এর বৈশিষ্ট্য কী কী? — সমস্যা সমাধানের সসীম, নিখুঁত ধাপের তালিকা; ইনপুট, আউটপুট, সসীমতা, নিখুঁততা, কার্যকারিতা।
  • Pseudocode আর flowchart-এর পার্থক্য? — একটি লেখায় সাজানো ধাপ, অন্যটি আকার ও তীর দিয়ে আঁকা ছবি; যুক্তি একই।
  • Dry run কাকে বলে? — কম্পিউটার ছাড়া, trace table-এ প্রতিটি ভ্যারিয়েবলের মান লিখে হাতে প্রোগ্রাম চালানো।
  • Binary search-এর শর্ত কী, কেন দ্রুত? — তালিকা সাজানো থাকতে হবে; প্রতি ধাপে অর্ধেক বাদ পড়ে, তাই O(log n).
  • Edge case বলতে কী বোঝেন? উদাহরণ দিন। — কিনারার ইনপুট যেখানে প্রোগ্রাম ভাঙতে পারে: খালি তালিকা, শূন্য দিয়ে ভাগ, ঋণাত্মক সংখ্যা।

ভাবনার প্রশ্ন

প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন। এগুলোই আপনাকে কোড-লেখক থেকে সমস্যা-সমাধানকারী বানাবে।

প্র ০১“Computational thinking সবার জন্য” — এই দাবি কে করেছিলেন, আর এর মানে কি সবাইকে প্রোগ্রামার হতে হবে?

২০০৬ সালে Carnegie Mellon বিশ্ববিদ্যালয়ের কম্পিউটার বিজ্ঞানী Jeannette Wing Communications of the ACM পত্রিকায় তিন পৃষ্ঠার একটি ছোট প্রবন্ধ লেখেন, শিরোনাম “Computational Thinking”. তাঁর মূল দাবি ছিল সাহসী: পড়া, লেখা আর অঙ্কের মতোই computational thinking প্রত্যেক মানুষের মৌলিক দক্ষতা হওয়া উচিত — শুধু কম্পিউটার বিজ্ঞানীদের নয়। শব্দটি তাঁর আগেও ব্যবহৃত হয়েছিল (যেমন শিক্ষাবিদ Seymour Papert-এর লেখায়), কিন্তু Wing-এর প্রবন্ধটিই বিশ্বজুড়ে আলোচনা শুরু করে দেয়।

তবে Wing নিজেই সাবধান করেছিলেন: computational thinking মানে প্রোগ্রামিং নয়, আর “কম্পিউটারের মতো ভাবা”-ও নয়। কম্পিউটার নিজে ভাবে না; এটি মানুষের ভাবার একটি ধরন — সমস্যাকে এমনভাবে গঠন করা যাতে তার সমাধান ধাপে ধাপে করা যায়, মানুষ বা যন্ত্র যে-ই করুক। তাঁর উদাহরণগুলো ছিল দৈনন্দিন: স্কুলব্যাগ গোছানোর সময় সারাদিনের দরকারি জিনিস আগে থেকে রাখা আসলে “prefetching” আর “caching”; সুপারমার্কেটের কোন লাইনে দাঁড়াবেন তা ঠিক করা একরকম কর্মক্ষমতার হিসাব।

বাংলাদেশের প্রেক্ষাপটে ভাবুন। একজন গার্মেন্টস কারখানার প্রোডাকশন ম্যানেজার যখন ঠিক করেন কোন লাইনে কোন অর্ডার যাবে যাতে শিপমেন্টের তারিখ মেলে, তিনি decomposition আর scheduling করছেন — একটি লাইন কোড না লিখেও। একজন ডাক্তার যখন উপসর্গ দেখে একে একে সম্ভাবনা বাদ দেন, তিনি একরকম search অ্যালগরিদম চালাচ্ছেন। প্রবন্ধটির পর অনেক দেশ স্কুলের পাঠ্যক্রমে computing বা computational thinking যোগ করে।

সমালোচনাও আছে: কেউ কেউ বলেন ধারণাটি এত বিস্তৃত যে প্রায় সব যুক্তিপূর্ণ চিন্তাকেই এর মধ্যে ফেলা যায়। এই বিতর্ক আজও চলছে। কিন্তু AI-এর যুগে Wing-এর মূল কথা আরও জোরালো হয়েছে: কোড লেখা যন্ত্র করতে পারে, কিন্তু সমস্যাটি সঠিকভাবে গঠন করা, কী ধরে নেওয়া হচ্ছে তা চেনা আর উত্তর যাচাই করা — এগুলো মানুষের কাজ।

মূল উপলব্ধি: computational thinking কোনো ভাষার নিয়ম নয়, একটি ভাবার অভ্যাস। Python শুধু সেই ভাবনা কম্পিউটারকে বোঝানোর একটি পরিষ্কার মাধ্যম।

প্র ০২“Algorithm” শব্দটি একজন মানুষের নাম থেকে এসেছে — তিনি কে, আর আধুনিক অর্থে অ্যালগরিদমের সংজ্ঞা কীভাবে পাকা হলো?

নবম শতকে বাগদাদে আব্বাসীয় খলিফাদের পৃষ্ঠপোষকতায় গড়ে ওঠে জ্ঞানচর্চার কেন্দ্র “বায়তুল হিকমাহ” (House of Wisdom). সেখানকার এক পণ্ডিত ছিলেন মুহাম্মদ ইবনে মুসা আল-খোয়ারিজমি — নামের শেষাংশ এসেছে মধ্য এশিয়ার খোয়ারিজম অঞ্চল থেকে। তিনি দুটি প্রভাবশালী বই লেখেন। একটিতে সমীকরণ সমাধানের পদ্ধতি; তার আরবি শিরোনামের “আল-জাবর” শব্দ থেকেই এসেছে algebra. আরেকটিতে ভারতীয় দশমিক অঙ্কপদ্ধতি — ০ থেকে ৯ আর স্থানমান দিয়ে হিসাব — ব্যাখ্যা করেন।

দ্বিতীয় বইটির মূল আরবি লেখা হারিয়ে গেছে, টিকে আছে লাতিন অনুবাদ, যার শুরু “Algoritmi de numero Indorum” দিয়ে। “Algoritmi” হলো তাঁর নামের লাতিন রূপ। মধ্যযুগের ইউরোপে নতুন দশমিক পদ্ধতিতে হিসাব করার নিয়মকেই বলা হতো “algorism”. পরে বানান বদলে হয় “algorithm”, আর অর্থ বিস্তৃত হয়ে দাঁড়ায় যেকোনো ধাপে ধাপে সমাধানের পদ্ধতি।

অথচ ধারণাটি নামের চেয়েও পুরোনো। প্রায় ২,৩০০ বছর আগে ইউক্লিড তাঁর “Elements” বইয়ে দুটি সংখ্যার গসাগু বের করার যে পদ্ধতি লেখেন — বড়টিকে ছোটটি দিয়ে ভাগ করে ভাগশেষ নিয়ে আবার ভাগ — তা আজও Python-এর math.gcd-এর মতো ফাংশনের পেছনের ধারণা।

আধুনিক, আনুষ্ঠানিক সংজ্ঞা আসে বিংশ শতকে। ১৯৩০-এর দশকে Alan Turing ও Alonzo Church “যান্ত্রিকভাবে হিসাব করা যায়” কথাটির গাণিতিক অর্থ দেন। আর ১৯৬৮ সালে Donald Knuth তাঁর বিখ্যাত বই “The Art of Computer Programming”-এর প্রথম খণ্ডে অ্যালগরিদমের পাঁচটি বৈশিষ্ট্য লেখেন: finiteness (সসীমতা), definiteness (নিখুঁততা), input, output আর effectiveness (প্রতিটি ধাপ বাস্তবে করা সম্ভব)। অংশ ৩-এর টেবিলটি এই তালিকারই সহজ রূপ।

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

প্র ০৩একজন গণিতবিদের ১৯৪৫ সালের বই কীভাবে আজকের প্রোগ্রামারদের সমস্যা সমাধানের পদ্ধতি হয়ে উঠল?

হাঙ্গেরিতে জন্ম নেওয়া গণিতবিদ George Pólya পরে যুক্তরাষ্ট্রের Stanford বিশ্ববিদ্যালয়ে পড়াতেন। ১৯৪৫ সালে প্রকাশিত হয় তাঁর ছোট বই “How to Solve It”. লক্ষ্য ছিল শিক্ষার্থীদের শেখানো কীভাবে অঙ্কের সমস্যা নিয়ে ভাবতে হয় — শুধু সূত্র মুখস্থ নয়। বইটি পরে বহু ভাষায় অনূদিত হয় এবং লক্ষ লক্ষ কপি বিক্রি হয়। তিনি সমাধানকে চারটি ধাপে ভাগ করেন:

  1. সমস্যা বোঝা: অজানা কী? কী কী দেওয়া আছে? শর্ত কী? — প্রোগ্রামিংয়ে: ইনপুট কী, আউটপুট কী, কোন নিয়ম মানতে হবে, edge case কী।
  2. পরিকল্পনা করা: আগে এমন কোনো সমস্যা দেখেছেন? ছোট বা সহজ রূপটি সমাধান করা যায়? — প্রোগ্রামিংয়ে: decomposition, pattern recognition, pseudocode.
  3. পরিকল্পনা বাস্তবায়ন: প্রতিটি ধাপ যত্ন করে করা এবং প্রতিটি ধাপ যে সঠিক তা যাচাই করা — প্রোগ্রামিংয়ে: কোড লেখা, ছোট ছোট অংশ চালিয়ে দেখা।
  4. ফিরে দেখা: ফলটি যাচাই করা যায়? অন্য পথে পাওয়া যায়? এই পদ্ধতি অন্য সমস্যায় কাজে লাগবে? — প্রোগ্রামিংয়ে: testing, dry run, কোড পরিষ্কার করা, শেখাটুকু লিখে রাখা।

খেয়াল করুন, নতুন প্রোগ্রামাররা প্রায়ই সরাসরি ধাপ ৩-এ চলে যান — আর AI-ও ঠিক তাই করে। ধাপ ১ বাদ দিলে ভুল সমস্যার নিখুঁত সমাধান হয়; ধাপ ৪ বাদ দিলে বাগ থেকে যায় আর শেখা হয় না। বিল-ভাগের উদাহরণে “সমান ভাগ নাকি যে যা খেয়েছে” প্রশ্নটি ধাপ ১-এর, আর “ভাগগুলো যোগ করলে ১,০০০ হয় কি না” ধাপ ৪-এর।

Pólya-র আরেকটি প্রিয় পরামর্শ: সমস্যা না মিললে একটি সহজতর সম্পর্কিত সমস্যা সমাধান করুন। প্রোগ্রামিংয়ে এটা খুব কাজের — ১০০ জনের তালিকায় আটকে গেলে ৩ জনের তালিকায় চেষ্টা করুন, বা খালি তালিকা দিয়ে শুরু করুন।

মূল উপলব্ধি: ভালো সমস্যা-সমাধানকারীর রহস্য প্রতিভা নয়, পদ্ধতি। প্রায় আশি বছর আগের চারটি ধাপ আজও যেকোনো কোডিং ইন্টারভিউ বা প্রজেক্টে সমান কার্যকর।

প্র ০৪Binary search-এর ধারণা এক বাক্যে বলা যায় — তবু অভিজ্ঞ প্রোগ্রামাররাও কেন এটি ভুল লেখেন?

Jon Bentley তাঁর বিখ্যাত বই “Programming Pearls”-এ একটি পরীক্ষার কথা লিখেছেন। পেশাদার প্রোগ্রামারদের কোর্সে তিনি সবাইকে binary search লিখতে দিতেন, পর্যাপ্ত সময় দিয়ে। তারপর একসাথে পরীক্ষা করে দেখা যেত, প্রায় ৯০ শতাংশের কোডেই বাগ আছে। Donald Knuth-ও লিখেছেন, binary search-এর ধারণা প্রথম প্রকাশিত হয় ১৯৪৬ সালে, কিন্তু সব আকারের তালিকায় নির্ভুলভাবে কাজ করা সংস্করণ প্রকাশ পেতে আরও প্রায় ষোলো বছর লেগে যায়।

ভুলগুলো সাধারণত সীমা নিয়ে: খোঁজার পরিসর low থেকে high — high কি পরিসরের ভেতরে, না বাইরে? লুপের শর্ত low < high নাকি low <= high? মাঝখান বাদ দেওয়ার সময় mid নাকি mid + 1? একটি ভুল জোড় হলেই হয় শেষ উপাদানটি কখনো খোঁজা হয় না, নয়তো দুই উপাদানের তালিকায় লুপ চিরকাল ঘুরতে থাকে। এটাই off-by-one-এর ক্লাসিক উদাহরণ।

সবচেয়ে বিখ্যাত ঘটনাটি ২০০৬ সালের। Google-এ কর্মরত Joshua Bloch — যিনি Java-র standard library-র অনেক অংশ লিখেছিলেন — একটি ব্লগ পোস্টে জানান, Java-র নিজস্ব Arrays.binarySearch-এ প্রায় নয় বছর ধরে একটি বাগ ছিল। বাগটি ছিল এক লাইনে: mid = (low + high) / 2. Java-র int প্রায় ২১৪ কোটির বেশি ধরতে পারে না; খুব বড় array-তে low + high সেই সীমা পেরিয়ে ঋণাত্মক হয়ে যায় (overflow), আর প্রোগ্রাম ভেঙে পড়ে। মজার ব্যাপার, Bentley-র বইয়ের কোডেও একই লাইন ছিল। সমাধান: low + (high - low) / 2.

Python-এ এই নির্দিষ্ট overflow হয় না, কারণ Python-এর int যত বড় খুশি হতে পারে। কিন্তু off-by-one-এর ঝুঁকি একই রয়ে যায়। তাই Python-এর standard library-তে আছে bisect module — বহু বছর ধরে লাখো মানুষের ব্যবহারে পরীক্ষিত। বাস্তব কাজে নিজে binary search না লিখে সেটি ব্যবহার করাই বুদ্ধিমানের কাজ।

মূল উপলব্ধি: “ধারণা বোঝা” আর “নির্ভুল কোড লেখা” দুটি আলাদা দক্ষতা। সীমার কাছের ইনপুট দিয়ে dry run, পরীক্ষিত library-র ব্যবহার আর বিনয় — তিনটিই দরকার।

প্র ০৫অনেকে বলেন abstraction-ই কম্পিউটার বিজ্ঞানের সবচেয়ে কেন্দ্রীয় দক্ষতা। কেন? আর abstraction কখন “ফুটো” হয়?

আপনি যখন Python-এ print("হ্যালো") লেখেন, তখন কী কী ঘটে ভাবুন: Python interpreter আপনার লেখা পড়ে, বাংলা অক্ষরগুলোকে Unicode থেকে বাইটে বদলায়, অপারেটিং সিস্টেমকে অনুরোধ পাঠায়, OS স্ক্রিনের driver-কে বলে, আর শেষে CPU-র কোটি কোটি transistor সুইচ করে। এর কিছুই আপনাকে জানতে হয়নি। প্রতিটি স্তর নিচের স্তরের জটিলতা লুকিয়ে একটি সহজ “হাতল” দিয়েছে। এটাই abstraction.

Jeannette Wing তাঁর প্রবন্ধে abstraction-কেই computational thinking-এর মূল বলেছেন। Edsger Dijkstra ১৯৭২ সালে তাঁর Turing Award ভাষণ “The Humble Programmer”-এ লিখেছিলেন — abstraction-এর উদ্দেশ্য অস্পষ্ট হওয়া নয়, বরং এমন একটি নতুন স্তর তৈরি করা যেখানে একদম নিখুঁত হওয়া যায়। অর্থাৎ বিস্তারিত বাদ দেওয়া মানে ঢিলেঢালা হওয়া নয়; বরং যা দরকার শুধু সেটুকু নিয়ে কঠোরভাবে ভাবা।

উদাহরণ: Python-এর sorted(). আপনি জানেন এটি তালিকা সাজায় — ব্যস। ভেতরে আছে Timsort, যা Tim Peters ২০০২ সালে Python-এর জন্য বানান, পরে Java ও অন্যান্য ভাষাও এটি নেয়। আপনার জানার দরকার নেই, কারণ abstraction ঠিকঠাক কাজ করছে। এই পর্বের অংশ ২-এ বাসের রুট-ম্যাপও ছিল একই জিনিস।

কিন্তু abstraction সবসময় নিখুঁত নয়। ২০০২ সালে Joel Spolsky “The Law of Leaky Abstractions” প্রবন্ধে লেখেন: সব অ-তুচ্ছ abstraction কোনো না কোনো মাত্রায় “ফুটো”। Python-এ একটি বিখ্যাত উদাহরণ: 0.1 + 0.2-এর ফল ঠিক 0.3 নয়, 0.30000000000000004. “দশমিক সংখ্যা” abstraction-এর নিচে লুকানো বাইনারি প্রতিনিধিত্ব এখানে বেরিয়ে পড়ে (পর্ব ০৭-এ দেখবেন)। আবার বড় ডেটায় একটি সহজ-দেখতে লাইন খুব ধীর হতে পারে, কারণ নিচে কী হচ্ছে জানা নেই।

তাই ভালো প্রোগ্রামার দুটোই পারেন: abstraction ব্যবহার করে দ্রুত এগোনো, আর দরকার হলে এক স্তর নিচে নেমে দেখা কী ঘটছে। এই কোর্সের পর্ব ০৫ (Python কীভাবে চলে) ঠিক সেই “নিচে নামা”র প্রথম ধাপ।

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

অনুশীলন

খাতা-কলম নিন। এখানে কোড লিখতে হবে না — ভাবা আর হাতে চালানোই আসল কাজ।

  1. দোকানের দিনশেষের স্টক: একটি মুদি দোকানে চাল, ডাল, তেল, চিনি — চারটি পণ্য। প্রতিদিন রাতে দোকানদার জানতে চান কোন পণ্য কতটা বাকি আর কোনটা আবার আনতে হবে। সমস্যাটিকে উপ-সমস্যায় ভাঙুন এবং বাংলায় pseudocode লিখুন।

    একটি সম্ভাব্য ভাঙন: (১) প্রতিটি পণ্যের সকালের মজুদ জানা, (২) দিনে নতুন কত এসেছে, (৩) কত বিক্রি হয়েছে, (৪) বাকি হিসাব করা, (৫) কোন পণ্য একটি সীমার নিচে নেমেছে তা দেখা, (৬) “আনতে হবে” তালিকা জানানো।

    প্রতিটি পণ্যের জন্য:
        বাকি = সকালের মজুদ + নতুন এসেছে − বিক্রি
        যদি বাকি < সর্বনিম্ন সীমা:
            "আনতে হবে" তালিকায় যোগ করো
    তালিকাটি দেখাও

    খেয়াল করুন: “সর্বনিম্ন সীমা” একটি নতুন ইনপুট, যা প্রশ্নে স্পষ্ট ছিল না — ভাঙতে গিয়েই বেরিয়ে এলো। আর edge case: বিক্রি মজুদের চেয়ে বেশি লেখা হলে বাকি ঋণাত্মক হবে — সেটি হিসাবের ভুল, দোকানদারকে জানানো উচিত।

  2. Trace table বানান: নিচের pseudocode-এর জন্য তালিকা [৪, ৭, ২, ৮] দিয়ে trace table বানান এবং শেষ আউটপুট বলুন। “যোগফল = ০; প্রতিটি সংখ্যা n-এর জন্য: যদি n জোড় হয়, যোগফল = যোগফল + n; শেষে যোগফল দেখাও।”
    ধাপnn জোড়?যোগফল
    শুরু——০
    ১৪হ্যাঁ৪
    ২৭না৪
    ৩২হ্যাঁ৬
    ৪৮হ্যাঁ১৪

    আউটপুট: ১৪. বাড়তি ভাবনা: খালি তালিকায় উত্তর ০ — এটি যুক্তিসংগত। সব বিজোড় সংখ্যার তালিকাতেও ০, যা থেকে বোঝা যায় না তালিকা খালি ছিল নাকি জোড় ছিল না।

  3. Edge case শিকারি: একটি প্রোগ্রাম শিক্ষার্থীদের নম্বরের গড় বের করে: “সব নম্বর যোগ করো, তারপর নম্বরের সংখ্যা দিয়ে ভাগ করো।” অন্তত পাঁচটি edge case লিখুন এবং প্রতিটিতে কী হওয়া উচিত বলুন।
    • খালি তালিকা: শূন্য দিয়ে ভাগ — প্রোগ্রাম ভেঙে পড়বে। “কোনো নম্বর নেই” জানানো উচিত।
    • একটিমাত্র নম্বর: গড় সেই নম্বরটিই — যাচাই করার সহজ উপায়।
    • ঋণাত্মক বা ১০০-র বেশি নম্বর: সম্ভবত টাইপের ভুল — বাতিল বা সতর্ক করা উচিত।
    • অনুপস্থিত শিক্ষার্থী: তাঁর নম্বর ০ ধরবেন, নাকি গড় থেকে বাদ দেবেন? এটি নীতির প্রশ্ন।
    • দশমিক গড়: ৭২.৬৬৬… — কত ঘর পর্যন্ত দেখাবেন, রাউন্ড করবেন কীভাবে?
    • সংখ্যার বদলে লেখা: কেউ “আশি” লিখলে বা ঘরটি ফাঁকা রাখলে কী হবে?
  4. AI অডিট: যেকোনো AI-কে বলুন: “একটা তালিকা থেকে দ্বিতীয় সর্বোচ্চ দাম খোঁজার অ্যালগরিদম pseudocode-এ দাও।” তারপর [৫০, ৫০, ৪০] আর [৫০] — এই দুটি তালিকায় তার অ্যালগরিদম dry run করুন। কী পেলেন?

    অনেক সময় AI-এর প্রথম উত্তর এমন হয়: “তালিকা সাজাও, শেষ থেকে দ্বিতীয়টি নাও।” [৫০, ৫০, ৪০]-এ সাজালে হয় [৪০, ৫০, ৫০], আর শেষ থেকে দ্বিতীয়টি ৫০ — অথচ “দ্বিতীয় সর্বোচ্চ ভিন্ন দাম” চাইলে উত্তর ৪০. আসলে কোনটি চান, প্রশ্নেই অস্পষ্ট ছিল — ঠিক এজন্যই ধাপ ১ (সমস্যা বোঝা) জরুরি। আর [৫০]-এ দ্বিতীয় কোনো দামই নেই — অনেক অ্যালগরিদম এখানে ভেঙে পড়ে বা ভুল কিছু ফেরত দেয়। এই দুটি ইনপুট দেখিয়ে AI-কে অ্যালগরিদম ঠিক করতে বলুন, আর আবার dry run করুন।

নিজেকে যাচাই করুন

ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।

ক্রমএকটি সমস্যা থেকে নির্ভরযোগ্য প্রোগ্রাম পর্যন্ত ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)

  1. 🎯 সমস্যা বোঝা — ইনপুট, আউটপুট আর নিয়ম ঠিক করা
  2. 🧩 সমস্যাটিকে ছোট উপ-সমস্যায় ভাঙা
  3. 📝 অ্যালগরিদম pseudocode-এ লেখা
  4. ✍️ খাতায় trace table দিয়ে dry run
  5. 🐍 Python-এ কোড লেখা ও চালানো
  6. 🔍 Edge case দিয়ে পরীক্ষা ও উত্তর মিলিয়ে দেখা

নিচের কোনটি একটি অ্যালগরিদমের আবশ্যিক বৈশিষ্ট্য?

  • এটি অবশ্যই Python-এ লেখা হতে হবে
  • এটি সীমিত ধাপে শেষ হয় এবং প্রতিটি ধাপ দ্ব্যর্থহীন
  • এটি অন্তত ১০০ লাইনের হতে হবে
  • “প্রয়োজনমতো” ধরনের নমনীয় নির্দেশ থাকা ভালো

বাসের রুট-ম্যাপে রাস্তার দোকান, গাছ বা ভবন না দেখিয়ে শুধু স্টপেজ ও লাইন দেখানো — computational thinking-এর কোন স্তম্ভের উদাহরণ?

  • Decomposition
  • Pattern recognition
  • Abstraction
  • Algorithm

তালিকা [৫, ৯, ৩] থেকে সর্বোচ্চ খোঁজার নিয়ম: “best = প্রথম সংখ্যা; প্রতিটি সংখ্যা m-এর জন্য, m > best হলে best = m.” লুপের প্রতিটি পাকের পর best-এর মান ক্রমানুসারে কী হবে?

  • ৫, ৯, ৯
  • ৫, ৯, ৩
  • ০, ৯, ৩
  • ৯, ৯, ৯

১,০০০ টাকার বিল ৩ জনে পূর্ণ টাকায় ভাগ করতে হবে, মোট যেন ঠিক ১,০০০ হয়। কোন ভাগটি সঠিক?

  • ৩৩৩.৩৩, ৩৩৩.৩৩, ৩৩৩.৩৩
  • ৩৩৩, ৩৩৩, ৩৩৩
  • ৩৩৪, ৩৩৪, ৩৩৪
  • ৩৩৪, ৩৩৩, ৩৩৩

সাজানো ১৬টি রোল নম্বরের তালিকায় binary search দিয়ে যেকোনো একটি রোল খুঁজতে সবচেয়ে খারাপ ক্ষেত্রে সর্বোচ্চ কতবার দেখতে হবে?

  • ১৬ বার
  • ৫ বার
  • ৮ বার
  • ১ বার

AI-কে দিয়ে একটি প্রোগ্রাম বানানোর সবচেয়ে নির্ভরযোগ্য পদ্ধতি কোনটি?

  • সরাসরি পুরো কোড চেয়ে, একবার চালিয়ে চললেই ব্যবহার করা
  • কোড পাওয়ার পর AI-কেই জিজ্ঞেস করা “এটা ঠিক আছে তো?”
  • আগে উপ-সমস্যা, অনুমান আর edge case চাওয়া; তারপর কোড নিয়ে নিজে dry run করা
  • যে AI সবচেয়ে লম্বা কোড দেয়, সেটি বেছে নেওয়া

শব্দকোষ

লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:

মনে রাখুন

  1. কম্পিউটার অনুমান করে না; ঝাপসা লক্ষ্যকে নিখুঁত ধাপে বদলানোই প্রোগ্রামিংয়ের আসল কাজ।
  2. চার স্তম্ভ: ভেঙে ফেলা, মিল খোঁজা, দরকারি অংশ রাখা, ধাপ সাজানো।
  3. অ্যালগরিদম সসীম ও নিখুঁত, স্পষ্ট ইনপুট ও আউটপুটসহ; Python-এ তা প্রায় pseudocode-এর মতোই দেখায়।
  4. কোডের আগে ও পরে trace table দিয়ে dry run, আর খালি, শূন্য, ঋণাত্মক, বড় ও বাংলা ইনপুটে edge case যাচাই।
  5. সাজানো তালিকায় অর্ধেক করে খোঁজা একে একে খোঁজার চেয়ে অনেক দ্রুত; AI-এর কাছে আগে পরিকল্পনা চান, পরে কোড।

পরের পর্বে: ভাবনা তৈরি — এবার যন্ত্র তৈরি। নিজের কম্পিউটারে Python ইনস্টল করা, REPL-এ এক লাইন করে কোড চালানো, VS Code সাজানো আর প্রথম .py স্ক্রিপ্ট চালানো।

আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ

এই পর্বটি শেয়ার করুন:
এই পর্বে ভুল পেয়েছেন? জানান