এই পর্বে যা শিখবেন
- প্রোগ্রাম আর প্রোগ্রামিং আসলে কী, আর AI-এর যুগেও কেন নিখুঁতভাবে ভাবতে শেখা দরকার
- প্রোগ্রামিং ভাষার প্রজন্ম (1GL–5GL), low-level আর high-level ভাষার সুবিধা-অসুবিধা
- assembler, compiler, interpreter, linker আর loader — কে কী করে, আর compiler বনাম interpreter তুলনা
- প্রোগ্রাম তৈরির ধাপ, ভুলের তিন ধরন (syntax, logic, runtime) আর debugging
- অ্যালগরিদমের বৈশিষ্ট্য, ফ্লোচার্টের প্রতীক, সিউডোকোড — আর পরীক্ষায় বারবার আসা ছয়টি উদাহরণ
১ · প্রোগ্রাম মানে নিখুঁত রেসিপি
মাকে চা বানাতে বললে আপনি শুধু বলেন “এক কাপ চা দাও”। চিনি কতটুকু, পানি কখন ফুটবে — মা নিজেই জানেন। এবার ভাবুন, এমন কাউকে চা বানাতে বলছেন যে জীবনে রান্নাঘর দেখেনি, আর আপনার প্রতিটি কথা অক্ষরে অক্ষরে মানে, একটুও বেশি-কম নয়। তখন বলতে হবে: “কেতলিতে এক কাপ পানি নাও। চুলা জ্বালাও। পানি না ফোটা পর্যন্ত অপেক্ষা করো। এক চামচ চা-পাতা দাও…” একটি ধাপ বাদ পড়লে বা অস্পষ্ট থাকলে চা হবে না।
কম্পিউটার ঠিক এই দ্বিতীয় ধরনের সহকারী। সে অবিশ্বাস্য দ্রুত, কখনো ক্লান্ত হয় না, কিন্তু নিজে থেকে কিছু আন্দাজ করে না। তাকে দিয়ে কাজ করাতে হলে ধাপগুলো নিখুঁতভাবে, নির্দিষ্ট ক্রমে লিখে দিতে হয়। এই ধাপের তালিকাই প্রোগ্রাম, আর তা লেখার কাজকে বলে প্রোগ্রামিং. যে কৃত্রিম ভাষায় লেখা হয় — C, Python, Java — তা প্রোগ্রামিং ভাষা.
প্রোগ্রাম লেখা তিন ধাপের কাজ: (১) ধাপগুলো ভাবা — অ্যালগরিদম; (২) ধাপগুলো আঁকা বা খসড়া লেখা — ফ্লোচার্ট বা সিউডোকোড; (৩) প্রোগ্রামিং ভাষায় লেখা — কোড। তারপর একটি অনুবাদক (compiler বা interpreter) সেই কোডকে CPU-র বোঝার মতো 0 আর 1-এ বদলে দেয়।
পর্ব ২৩-এ দেখেছেন, কম্পিউটার তলায় তলায় সাজানো, আর প্রোগ্রামিং ভাষা তার একটি তলা — নিচে machine code, ওপরে মানুষের চিন্তা। এই পর্বে সেই তলায় ঢুকবেন। পরের দুই পর্বে (৩৯ আর ৪০) C ভাষায় সত্যিকারের প্রোগ্রাম লিখবেন; এখানে শিখবেন কোড লেখার আগের চিন্তাটুকু, যা যেকোনো ভাষাতেই কাজে লাগে।
AI কোড লিখে দিলে প্রোগ্রামিং শিখব কেন?
প্রশ্নটি যৌক্তিক। আজ ChatGPT বা Copilot-কে বললেই কোড লিখে দেয়। কিন্তু খেয়াল করুন, AI-কে যা বলবেন, সে সেটাই বানাবে — আপনি যা বোঝাতে চেয়েছিলেন তা নয়। “ছাত্রদের গড় নম্বর বের করো” বললে AI জানে না অনুপস্থিত ছাত্রকে শূন্য ধরবে, না বাদ দেবে। প্রোগ্রামিং শেখার আসল লাভ তাই কোডের নিয়ম মুখস্থ করা নয়, নিখুঁতভাবে ভাবতে শেখা: সমস্যাকে ছোট ধাপে ভাঙা, প্রতিটি সম্ভাবনা ভেবে রাখা, আর ফল যাচাই করা। এই দক্ষতা অফিসের কাজের নিয়ম লেখা থেকে Excel-এর সূত্র বানানো পর্যন্ত সবখানে লাগে।
২ · প্রোগ্রামিং ভাষার পাঁচ প্রজন্ম
প্রথম দিকের কম্পিউটারে প্রোগ্রাম লেখা হতো সরাসরি 0 আর 1 দিয়ে। তারপর ধাপে ধাপে ভাষাগুলো মানুষের ভাষার কাছাকাছি এসেছে। এই ধাপগুলোকে বলা হয় প্রোগ্রামিং ভাষার প্রজন্ম (generation). পাঠ্যবই আর চাকরির পরীক্ষায় এই টেবিলটি খুব গুরুত্বপূর্ণ:
| প্রজন্ম | ভাষা | কেমন দেখতে | উদাহরণ |
|---|---|---|---|
| 1GL | Machine language | শুধু 0 আর 1; CPU সরাসরি বোঝে, অনুবাদক লাগে না | 10110000 01100001 |
| 2GL | Assembly language | 0/1-এর বদলে ছোট ইংরেজি সংকেত (mnemonic) | MOV AL, 61h, ADD |
| 3GL | High-level language | ইংরেজি শব্দ আর গণিতের চিহ্ন; কীভাবে করতে হবে ধাপে ধাপে বলা হয় | FORTRAN, COBOL, BASIC, C, C++, Java, Python |
| 4GL | চতুর্থ প্রজন্মের ভাষা | কী চাই শুধু তা বলা হয়, কীভাবে তা নয়; ডেটাবেস আর রিপোর্টের কাজে | SQL, রিপোর্ট জেনারেটর |
| 5GL | পঞ্চম প্রজন্মের ভাষা | তথ্য আর নিয়ম দিলে কম্পিউটার নিজে সমাধান খোঁজে; AI-গবেষণায় | Prolog, Mercury; স্বাভাবিক ভাষা (natural language) |
একই কাজ তিন প্রজন্মে দেখুন — “a আর b যোগ করে c-তে রাখো”:
2GL (assembly) : MOV AX, a ADD AX, b MOV c, AX
3GL (C) : c = a + b;
4GL (SQL) : SELECT a + b AS c FROM numbers;
4GL-এ খেয়াল করুন, আপনি বলছেন কী চান; টেবিলের প্রতিটি সারি কীভাবে পড়বে, তা ভাষা নিজেই ঠিক করে। SQL নিয়ে বিস্তারিত পর্ব ৪২-এ।
Low-level বনাম high-level
প্রথম দুই প্রজন্মকে বলে low-level language — যন্ত্রের কাছাকাছি, মানুষের থেকে দূরে। তৃতীয় থেকে high-level. “Low” মানে খারাপ নয়; মানে হার্ডওয়্যারের কাছের তলা।
| বিষয় | Low-level (machine, assembly) | High-level (C, Python, Java) |
|---|---|---|
| লেখা ও পড়া | কঠিন, সময়সাপেক্ষ | সহজ, ইংরেজির কাছাকাছি |
| যন্ত্রের ওপর নির্ভরতা | যন্ত্রনির্ভর (machine dependent) — এক CPU-র কোড অন্যটিতে চলে না | যন্ত্র-নিরপেক্ষ — একই কোড নানা কম্পিউটারে চলে (portability) |
| গতি ও মেমরি | খুব দ্রুত, কম মেমরি — হার্ডওয়্যারের ওপর পূর্ণ নিয়ন্ত্রণ | সাধারণত একটু ধীর, তবে ভালো compiler পার্থক্য প্রায় মুছে দেয় |
| অনুবাদক | machine: লাগে না; assembly: assembler | compiler বা interpreter |
| ভুল খোঁজা | কঠিন | তুলনামূলক সহজ |
| কোথায় লাগে | driver, firmware, ছোট যন্ত্রের চিপ | অ্যাপ, ওয়েবসাইট, ব্যাংকের সফটওয়্যার — প্রায় সবকিছু |
C-কে অনেক বইয়ে “middle-level language” বলা হয়, কারণ এটি high-level হলেও মেমরির ঠিকানা আর bit ধরে কাজ করতে দেয় — assembly-র অনেক ক্ষমতা হাতে রাখে। তাই অপারেটিং সিস্টেম আর driver লেখায় C আজও প্রধান।
৩ · অনুবাদক — assembler, compiler আর interpreter
CPU বোঝে শুধু তার নিজের machine code. তাই assembly বা high-level ভাষায় লেখা কোডকে (source code) machine code-এ বদলাতে হয়। এই কাজ করে যে সিস্টেম সফটওয়্যার, তার নাম অনুবাদক প্রোগ্রাম (language translator). তিন ধরন:
Assembler
assembly ভাষার কোডকে machine code-এ রূপান্তর করে। প্রায় এক লাইন = এক নির্দেশ, তাই কাজটি সরল।
Compiler
পুরো প্রোগ্রাম একবারে পড়ে অনুবাদ করে, একটি আলাদা machine code ফাইল (object code) বানায়, যা linker জোড়া দিলে চালানো যায় এমন ফাইল হয় (Windows-এ .exe ফাইল)। সব ভুল একসাথে তালিকা করে দেখায়। উদাহরণ: C, C++.
Interpreter
একটি করে লাইন পড়ে, অনুবাদ করে, সাথে সাথে চালায়। কোনো লাইনে ভুল পেলে সেখানেই থেমে যায়। উদাহরণ: Python, পুরোনো BASIC, ব্রাউজারে JavaScript.
উপমা — দোভাষী আর অনুবাদক: একটি ইংরেজি বই বাংলায় পড়তে চান। এক উপায়: একজন অনুবাদক পুরো বইটি আগে অনুবাদ করে ছাপিয়ে দিলেন — সময় লাগল, কিন্তু এরপর যতবার ইচ্ছা দ্রুত পড়া যায়, অনুবাদকের আর দরকার নেই (compiler). আরেক উপায়: একজন দোভাষী পাশে বসে প্রতিটি বাক্য পড়ে শোনাচ্ছেন — সাথে সাথে শুরু করা যায়, কিন্তু প্রতিবার পড়তে দোভাষী লাগে, আর গতিও কম (interpreter).
নিচের stepper-এ একই পাঁচ লাইনের প্রোগ্রাম দুই ধরনের অনুবাদককে দেওয়া হয়েছে। লাইন ৪-এ একটি বানান ভুল: print-এর বদলে prnt. দেখুন কে কখন ভুল ধরে।
1a = 102b = 203print(a + b)4prnt(a * b) # বানান ভুল5print("done")
| Compiler | |
| Compiler-এর পর্দায় | |
| Interpreter | |
| Interpreter-এর পর্দায় |
- একই প্রোগ্রাম, দুই অনুবাদক। লাইন ৪-এ
prntলেখা — এমন কোনো নির্দেশ নেই। বাকি সব লাইন ঠিক। (বোঝার সুবিধার জন্য একটি সাধারণ, Python-এর মতো দেখতে কোড নেওয়া হয়েছে।) - Compiler আগে পুরোটা পড়ে। চালানোর আগেই সে পাঁচটি লাইন যাচাই করে আর লাইন ৪-এর ভুল খুঁজে পায়। ওদিকে interpreter সরাসরি লাইন ১ চালিয়ে দিয়েছে — তার কাছে লাইন ৪ এখনো অজানা।
- Compiler অনুবাদ বাতিল করল। ভুল থাকলে compiler কোনো চালানো যায় এমন ফাইল বানায় না। Interpreter লাইন ২ চালাচ্ছে।
- Interpreter আউটপুট দিতে শুরু করেছে। লাইন ৩ চলে পর্দায় 30 এসেছে। compiler-এর দিকে এখনো কিছুই চলেনি।
- Interpreter লাইন ৪-এ থামল। 30 ছাপা হয়ে গেছে, তারপর ভুলের বার্তা। লাইন ৫ কখনো চলেনি। অর্থাৎ interpreter-এ ভুল ধরা পড়ে ঠিক যে লাইনে পৌঁছায় তখন — প্রোগ্রামের যে অংশ কখনো চলে না, সেখানকার ভুল লুকিয়ে থাকতে পারে।
- ভুল ঠিক করার পর। দুজনেই একই ফল দেয়: 30, 200, done. পার্থক্য পরের বারগুলোতে: compiler-এর বানানো .exe অনুবাদ ছাড়াই দ্রুত চলে; interpreter প্রতিবার নতুন করে অনুবাদ করে।
Compiler বনাম interpreter — পরীক্ষার ক্লাসিক টেবিল
| বিষয় | Compiler | Interpreter |
|---|---|---|
| অনুবাদের একক | পুরো প্রোগ্রাম একসাথে | এক লাইন করে |
| Object program | তৈরি করে (আলাদা ফাইল) | তৈরি করে না |
| ভুল দেখানো | অনুবাদ শেষে সব ভুল একসাথে | যে লাইনে ভুল, সেখানেই থেমে |
| চলার গতি | দ্রুত (অনুবাদ আগেই শেষ) | ধীর (চলার সময় অনুবাদ) |
| ভুল খোঁজা (debugging) | তুলনামূলক কঠিন | সহজ — ঠিক কোথায় থামল দেখা যায় |
| মেমরি | অনুবাদের সময় বেশি লাগে | কম লাগে |
| আবার চালাতে | অনুবাদক লাগে না | প্রতিবার লাগে |
| উদাহরণ | C, C++, FORTRAN, COBOL | Python, BASIC, JavaScript (মূলত) |
দুটো মিলিয়ে — Java-র পথ
Java কোড প্রথমে compile হয়, কিন্তু কোনো নির্দিষ্ট CPU-র machine code-এ নয় — একটি মাঝামাঝি কোডে, যার নাম bytecode (.class ফাইল)। তারপর যেকোনো কম্পিউটারে বসানো JVM (Java Virtual Machine) সেই bytecode পড়ে চালায়। ফলে একবার compile করা Java প্রোগ্রাম Windows, Linux বা Mac — যেখানে JVM আছে সেখানেই চলে। আজকের JVM, ব্রাউজারের JavaScript-ইঞ্জিন আর PyPy-র মতো কিছু Python ব্যবস্থা বারবার চলা অংশগুলো চলার মাঝেই machine code-এ বদলে নেয় — এই কৌশলের নাম JIT compiler. তাই “compiled না interpreted” প্রশ্নটি আসলে ভাষার নয়, ভাষা চালানোর ব্যবস্থার।
অনুবাদের পরে — linker আর loader
- Linker — compiler-এর বানানো এক বা একাধিক object ফাইল আর library-র তৈরি কোড (যেমন পর্দায় লেখা ছাপার ফাংশন) জোড়া লাগিয়ে একটি চালানোর উপযোগী ফাইল বানায়।
- Loader — অপারেটিং সিস্টেমের অংশ; আপনি প্রোগ্রাম চালাতে বললে সেটিকে স্টোরেজ থেকে RAM-এ তুলে CPU-কে চালাতে দেয়।
source code (main.c) → [compiler] → object code (main.o) → [linker + library] → main.exe → [loader] → RAM-এ চলছে
৪ · প্রোগ্রাম তৈরির ধাপ আর ভুলের তিন ধরন
বড় একটি ভবন বানাতে কেউ সরাসরি ইট গাঁথা শুরু করে না — আগে জমি মাপা, নকশা, তারপর নির্মাণ, পরীক্ষা, শেষে রক্ষণাবেক্ষণ। প্রোগ্রামও তেমনি। প্রোগ্রাম তৈরির এই ধাপগুলোকে বলে program development life cycle:
- সমস্যা বিশ্লেষণ: কী ইনপুট আসবে, কী আউটপুট চাই, কোন নিয়ম মানতে হবে। যেমন: “ছাত্রের নম্বর দিলে গ্রেড দেখাও — 80 বা তার বেশি হলে A+.”
- অ্যালগরিদম তৈরি: সমাধানের ধাপগুলো সাধারণ ভাষায় লেখা।
- ফ্লোচার্ট বা সিউডোকোড: ধাপগুলোকে ছবিতে বা খসড়া কোডে সাজানো, যাতে যুক্তির ফাঁক চোখে পড়ে।
- কোডিং: নির্দিষ্ট প্রোগ্রামিং ভাষায় লেখা।
- Compile, পরীক্ষা আর debugging: অনুবাদ করা, নানা ইনপুট দিয়ে চালানো, ভুল খুঁজে ঠিক করা।
- ডকুমেন্টেশন: প্রোগ্রাম কী করে, কীভাবে ব্যবহার করতে হয়, কোডের কোন অংশ কী — লিখে রাখা।
- রক্ষণাবেক্ষণ: নতুন নিয়ম এলে বা ভুল ধরা পড়লে বদলানো। বাস্তব সফটওয়্যারের জীবনের বেশিরভাগ সময় এই ধাপেই কাটে।
ভুলের তিন ধরন
প্রোগ্রামের ভুলকে বলে bug. ভুল তিন রকম, আর পরীক্ষায় উদাহরণ দেখে ধরন চিনতে বলা হয়:
| ধরন | কী | ছোট উদাহরণ (C) | কে ধরে |
|---|---|---|---|
| Syntax error | ভাষার ব্যাকরণ ভাঙা — বানান, বন্ধনী, সেমিকোলন | printf("Hi") — শেষে ; নেই | compiler/interpreter, চালানোর আগেই |
| Logic error | ব্যাকরণ ঠিক, প্রোগ্রাম চলে, কিন্তু ফল ভুল | avg = a + b / 2; — আগে ভাগ হয়, তাই 10 আর 20-এর গড় আসে 20 | কেউ নয় — পরীক্ষা করে মানুষকেই ধরতে হয় |
| Runtime error | চলার মাঝে অসম্ভব কোনো কাজে প্রোগ্রাম আটকে যায় | x = 10 / n; — ব্যবহারকারী n = 0 দিলে শূন্য দিয়ে ভাগ | চলার সময় ধরা পড়ে, প্রায়ই নির্দিষ্ট ইনপুটে |
logic error সবচেয়ে বিপজ্জনক, কারণ কেউ সতর্ক করে না — প্রোগ্রাম আত্মবিশ্বাসের সাথে ভুল উত্তর দেয়। ঠিক রূপ: avg = (a + b) / 2;. ভুল খুঁজে বের করে ঠিক করার কাজকে বলে debugging. এর সবচেয়ে সহজ হাতিয়ার কাগজে-কলমে প্রোগ্রামটি হাতে চালিয়ে দেখা — dry run, যা অংশ ৬-এ করবেন।
৫ · অ্যালগরিদম, ফ্লোচার্ট আর সিউডোকোড
অ্যালগরিদম ও তার পাঁচ বৈশিষ্ট্য
কোনো সমস্যা সমাধানের জন্য ধাপে ধাপে সাজানো, সসীম সংখ্যক সুনির্দিষ্ট নির্দেশের সমষ্টিকে বলে অ্যালগরিদম. রান্নার রেসিপি, ATM থেকে টাকা তোলার নিয়ম, এমনকি গুণ করার পদ্ধতিও অ্যালগরিদম। কিন্তু কম্পিউটারের জন্য অ্যালগরিদমকে পাঁচটি শর্ত মানতে হয়:
| বৈশিষ্ট্য | মানে | না মানলে কী হয় |
|---|---|---|
| ইনপুট (input) | শূন্য বা তার বেশি ইনপুট নেয় | — |
| আউটপুট (output) | অন্তত একটি ফল দেয় | ফলহীন কাজ অর্থহীন |
| সুনির্দিষ্টতা (definiteness) | প্রতিটি ধাপ স্পষ্ট, একটিই অর্থ | “একটু লবণ দাও” — কতটুকু? দুজন দুরকম করবে |
| সসীমতা (finiteness) | সসীম ধাপে শেষ হয় | লুপ কখনো থামে না — প্রোগ্রাম আটকে থাকে |
| কার্যকারিতা (effectiveness) | প্রতিটি ধাপ বাস্তবে করা সম্ভব, মৌলিক | “সবচেয়ে বড় মৌলিক সংখ্যা বের করো” — অসম্ভব |
ফ্লোচার্ট — অ্যালগরিদমের ছবি
অ্যালগরিদমকে নির্দিষ্ট কিছু প্রতীক আর তীর দিয়ে আঁকলে তাকে বলে ফ্লোচার্ট. ছবিতে যুক্তির পথ এক নজরে দেখা যায় — কোথায় সিদ্ধান্ত, কোথায় পুনরাবৃত্তি। প্রতীকগুলো আন্তর্জাতিকভাবে প্রমিত (ANSI, পরে ISO 5807):
| প্রতীক | নাম | ব্যবহার |
|---|---|---|
| Terminal (শুরু/শেষ) | ডিম্বাকার বা গোল-কোণা আয়ত। প্রতিটি ফ্লোচার্টে একটি শুরু, একটি শেষ | |
| Input/Output | সামান্তরিক। ইনপুট নেওয়া বা ফল দেখানো/ছাপানো | |
| Process (প্রক্রিয়া) | আয়ত। হিসাব বা মান রাখা, যেমন sum = a + b | |
| Decision (সিদ্ধান্ত) | রম্বস বা হীরক (◇)। হ্যাঁ/না প্রশ্ন; একটি পথ ঢোকে, দুটি বের হয় | |
| Connector (সংযোগ) | ছোট বৃত্ত। ফ্লোচার্ট বড় হলে দূরের দুই অংশ একই অক্ষর দিয়ে জোড়া | |
| Flow line (প্রবাহ রেখা) | তীর। কোন ধাপের পর কোন ধাপ, তার দিক দেখায় |
ফ্লোচার্ট আঁকার নিয়ম: (১) প্রবাহ সাধারণত ওপর থেকে নিচে, বাঁ থেকে ডানে; (২) একটি শুরু আর একটি শেষ; (৩) প্রতিটি প্রতীকে ছোট, স্পষ্ট লেখা; (৪) প্রতিটি সিদ্ধান্ত-প্রতীক থেকে দুটি পথ, “হ্যাঁ” আর “না” লেবেলসহ; (৫) প্রবাহ রেখা যেন একে অপরকে না কাটে; (৬) কোনো পথ যেন ঝুলে না থাকে — প্রতিটি পথ শেষে গিয়ে মেলে।
সিউডোকোড — ভাষা-নিরপেক্ষ খসড়া কোড
সিউডোকোড (pseudo = নকল) হলো কোডের মতো করে লেখা অ্যালগরিদম, কিন্তু কোনো নির্দিষ্ট ভাষার কঠোর ব্যাকরণ ছাড়া। INPUT, IF … THEN … ELSE, WHILE, PRINT-এর মতো কিছু শব্দ ব্যবহার হয়। কম্পিউটার এটি চালাতে পারে না; এটি মানুষের জন্য, যাতে পরে যেকোনো ভাষায় সহজে কোড লেখা যায়।
উদাহরণ ১ · দুটি সংখ্যার যোগফল (sequence)
ধাপ ১: শুরু
ধাপ ২: দুটি সংখ্যা A আর B ইনপুট নাও
ধাপ ৩: S = A + B হিসাব করো
ধাপ ৪: S প্রিন্ট করো
ধাপ ৫: শেষ
BEGIN
INPUT A, B
S ← A + B
PRINT S
END
উদাহরণ ২ · তিনটি সংখ্যার মধ্যে বড়টি (selection)
পরীক্ষায় সবচেয়ে বেশি আসা ফ্লোচার্ট। আগে অ্যালগরিদম, তারপর নিচের stepper-এ ফ্লোচার্টটি একটি নমুনা ইনপুট দিয়ে “চালিয়ে” দেখুন।
ধাপ ১: শুরু
ধাপ ২: A, B, C ইনপুট নাও
ধাপ ৩: A > B হলে ধাপ ৪-এ যাও, না হলে ধাপ ৫-এ
ধাপ ৪: A > C হলে A প্রিন্ট করো, না হলে C প্রিন্ট করো; ধাপ ৬-এ যাও
ধাপ ৫: B > C হলে B প্রিন্ট করো, না হলে C প্রিন্ট করো
ধাপ ৬: শেষ
BEGIN
INPUT A, B, C
IF A > B THEN
IF A > C THEN PRINT A ELSE PRINT C
ELSE
IF B > C THEN PRINT B ELSE PRINT C
END IF
END
| সক্রিয় প্রতীক | |
| A, B, C | |
| প্রশ্ন → উত্তর | |
| আউটপুট |
- শুরু। প্রতিটি ফ্লোচার্ট একটি ডিম্বাকার terminal প্রতীক দিয়ে শুরু হয়। এখনো কোনো মান নেই।
- ইনপুট। সামান্তরিক প্রতীকে তিনটি সংখ্যা নেওয়া হলো: A = 12, B = 25, C = 7.
- প্রথম সিদ্ধান্ত: A > B? 12 > 25 — না। রম্বস থেকে দুটি পথ বের হয়েছে; উত্তর “না”, তাই ডান দিকের পথ। বাঁ দিকের পুরো অংশ (A > C?) এবার আর দেখাই হবে না।
- দ্বিতীয় প্রশ্ন: B > C? আমরা জানি B ≥ A; এখন 25 > 7 — হ্যাঁ। মাত্র দুটি তুলনাতেই উত্তর মিলে গেল।
- আউটপুট: 25. “প্রিন্ট B” প্রতীক থেকে পর্দায় 25. এবার ভাবুন, A = 9, B = 4, C = 15 হলে কোন পথ? (A > B হ্যাঁ → A > C না → প্রিন্ট C.)
- শেষ। তিনটি প্রিন্ট-প্রতীকের পথই নিচে একটি রেখায় মিলে একটিমাত্র “শেষ”-এ যায় — ফ্লোচার্টে কোনো পথ ঝুলে থাকে না।
উদাহরণ ৩ · সংখ্যাটি জোড় না বিজোড়
কোনো সংখ্যাকে 2 দিয়ে ভাগ করলে ভাগশেষ 0 হলে জোড়। প্রোগ্রামিংয়ে ভাগশেষ বের করার চিহ্ন % (modulus), যেমন 7 % 2 = 1.
ধাপ ১: শুরু
ধাপ ২: N ইনপুট নাও
ধাপ ৩: N % 2 = 0 হলে “জোড়” প্রিন্ট করো, না হলে “বিজোড়” প্রিন্ট করো
ধাপ ৪: শেষ
BEGIN
INPUT N
IF N MOD 2 = 0 THEN
PRINT "জোড়"
ELSE
PRINT "বিজোড়"
END IF
END
৬ · লুপ — যোগফল, ফ্যাক্টোরিয়াল আর লিপ ইয়ার
“1 থেকে 100 পর্যন্ত যোগ করো” — প্রতিটি যোগ আলাদা ধাপে লিখলে ১০০টি ধাপ। তার বদলে একই ধাপ বারবার করানো যায়, যতক্ষণ একটি শর্ত সত্য থাকে। একে বলে লুপ (loop). ফ্লোচার্টে লুপ মানে একটি তীর, যা আবার পেছনে সিদ্ধান্ত-প্রতীকে ফিরে যায়। মান মনে রাখার জন্য লাগে ভ্যারিয়েবল — নাম দেওয়া একটি খালি বাক্স, যার মান বদলাতে পারে; এখানে sum আর i.
উদাহরণ ৪ · 1 থেকে n পর্যন্ত যোগফল
ধাপ ১: শুরু
ধাপ ২: n ইনপুট নাও
ধাপ ৩: sum = 0, i = 1 ধরো
ধাপ ৪: i ≤ n না হলে ধাপ ৭-এ যাও
ধাপ ৫: sum = sum + i
ধাপ ৬: i = i + 1; ধাপ ৪-এ ফিরে যাও
ধাপ ৭: sum প্রিন্ট করো
ধাপ ৮: শেষ
এবার সিউডোকোডটি n = 4 দিয়ে হাতে চালান — একেই বলে dry run বা trace. প্রতিটি ধাপে ভ্যারিয়েবলের মান একটি টেবিলে (trace table) লিখে রাখা হয়।
1BEGIN2INPUT n3sum ← 0 ; i ← 14WHILE i ≤ n DO5 sum ← sum + i6 i ← i + 17END WHILE8PRINT sum9END
| n | |
| i | |
| sum | |
| i ≤ n ? |
- ইনপুট: n = 4. অর্থাৎ 1 + 2 + 3 + 4 বের করতে হবে। sum আর i-এর মান এখনো অজানা (?).
- শুরুর মান (initialization): sum = 0, i = 1. sum-কে 0 দিয়ে শুরু না করলে আগের আবর্জনা মান যোগ হয়ে যেত — একটি সাধারণ logic error.
- শর্ত যাচাই: 1 ≤ 4 — সত্য, তাই লুপের ভেতরে ঢুকবে।
- প্রথম পাক: sum = 0 + 1 = 1, তারপর i = 2. ফিরে গিয়ে শর্ত: 2 ≤ 4 সত্য।
- দ্বিতীয় পাক: sum = 1 + 2 = 3, i = 3. শর্ত 3 ≤ 4 সত্য।
- তৃতীয় পাক: sum = 3 + 3 = 6, i = 4. শর্ত 4 ≤ 4 — সমান, তাই এখনো সত্য। এখানে ≤ না লিখে < লিখলে 4 যোগ হতো না — ফল আসত 6.
- চতুর্থ পাক: sum = 6 + 4 = 10, i = 5. শর্ত 5 ≤ 4 — মিথ্যা।
- লুপ শেষ। লক্ষ করুন i এখন 5, n-এর চেয়ে এক বেশি — লুপ থামার কারণ এটাই। i = i + 1 লাইনটি ভুলে গেলে i চিরকাল 1 থাকত, শর্ত কখনো মিথ্যা হতো না — অসীম লুপ, অ্যালগরিদমের “সসীমতা” ভঙ্গ।
- আউটপুট: 10. যাচাই করুন: 1 + 2 + 3 + 4 = 10, আবার সূত্রে n(n + 1)/2 = 4 × 5 / 2 = 10. দুই পথে মিলে গেল — এটাই পরীক্ষা করার ভালো অভ্যাস।
উদাহরণ ৫ · ফ্যাক্টোরিয়াল (n!)
n! = 1 × 2 × 3 × … × n; যেমন 5! = 120, আর সংজ্ঞা অনুযায়ী 0! = 1. ফ্লোচার্ট হুবহু ওপরের মতো, শুধু দুটি বদল: শুরুর মান fact = 1 (গুণের জন্য 0 নয়, 1 — নইলে সব গুণফল 0), আর লুপে fact = fact × i.
BEGIN
INPUT n
fact ← 1 ; i ← 1
WHILE i ≤ n DO
fact ← fact × i
i ← i + 1
END WHILE
PRINT fact
END
উদাহরণ ৬ · লিপ ইয়ার (অধিবর্ষ)
অনেকে ভাবেন “৪ দিয়ে বিভাজ্য হলেই লিপ ইয়ার”। পুরো নিয়ম (Gregorian ক্যালেন্ডার): ৪০০ দিয়ে বিভাজ্য হলে লিপ ইয়ার; না হলে ১০০ দিয়ে বিভাজ্য হলে লিপ ইয়ার নয়; না হলে ৪ দিয়ে বিভাজ্য হলে লিপ ইয়ার; বাকি সব নয়। প্রশ্নের ক্রম গুরুত্বপূর্ণ — নিচে চারটি সাল দিয়ে দেখুন।
BEGIN
INPUT Y
IF Y MOD 400 = 0 THEN PRINT "লিপ ইয়ার"
ELSE IF Y MOD 100 = 0 THEN PRINT "লিপ ইয়ার নয়"
ELSE IF Y MOD 4 = 0 THEN PRINT "লিপ ইয়ার"
ELSE PRINT "লিপ ইয়ার নয়"
END
| সাল (Y) | |
| উত্তরগুলো | |
| ফল |
- 2024: ৪০০ দিয়ে নয়, ১০০ দিয়েও নয়, কিন্তু ৪ দিয়ে বিভাজ্য — লিপ ইয়ার। তিনটি প্রশ্নই করতে হলো।
- 2023: কোনোটি দিয়েই বিভাজ্য নয় — সাধারণ বছর।
- 1900: ৪ দিয়ে বিভাজ্য, তবুও লিপ ইয়ার নয় — কারণ ১০০ দিয়ে বিভাজ্য। দ্বিতীয় প্রশ্নেই উত্তর মিলেছে, তৃতীয়টি করা হয়নি। শুধু “৪ দিয়ে বিভাজ্য?” দেখলে এখানে ভুল হতো — একটি আদর্শ edge case.
- 2000: ১০০ দিয়ে বিভাজ্য হলেও ৪০০ দিয়েও বিভাজ্য — লিপ ইয়ার। প্রথম প্রশ্নেই উত্তর। প্রশ্নের ক্রম উল্টে আগে ১০০ যাচাই করলে 2000-কে ভুলে “নয়” বলত।
নিজে চালিয়ে দেখুন — ফ্লোচার্ট চালানোর যন্ত্র
নিচের কোডে দুটি ফ্লোচার্ট ডেটা হিসেবে রাখা আছে — প্রতিটি প্রতীক একটি node, আর প্রতিটি node জানে পরের node কোনটি। সিদ্ধান্ত-প্রতীকের দুটি “পরের node” থাকে: হ্যাঁ আর না। ছোট্ট run ফাংশনটি START থেকে শুরু করে তীর ধরে ধরে হাঁটে আর যে পথে গেল তা ছাপে। “Run” চাপুন।
// প্রতিটি node: [লেবেল, কাজ বা শর্ত, পরের node, শর্ত মিথ্যা হলে যে node]
const largest = {
S: ['START', null, 'I'], I: ['INPUT A,B,C', null, 'D1'],
D1: ['A>B?', v => v.A > v.B, 'D2', 'D3'],
D2: ['A>C?', v => v.A > v.C, 'PA', 'PC'],
D3: ['B>C?', v => v.B > v.C, 'PB', 'PC'],
PA: ['PRINT A', v => v.out = v.A, 'E'], PB: ['PRINT B', v => v.out = v.B, 'E'], PC: ['PRINT C', v => v.out = v.C, 'E'] };
const sumN = {
S: ['START', null, 'I'], I: ['INPUT n', null, 'P0'],
P0: ['sum=0,i=1', v => { v.sum = 0; v.i = 1; }, 'D'],
D: ['i<=n?', v => v.i <= v.n, 'P1', 'O'],
P1: ['sum=sum+i,i=i+1', v => { v.sum += v.i; v.i++; }, 'D'],
O: ['PRINT sum', v => v.out = v.sum, 'E'] };
function run(title, chart, v) {
let id = 'S'; const path = [];
while (id !== 'E') {
const [label, f, yes, no] = chart[id];
if (no) { const ok = f(v); path.push(label + (ok ? ' Yes' : ' No')); id = ok ? yes : no; } // decision (রম্বস)
else { path.push(label); if (f) f(v); id = yes; } // terminal, I/O, process
}
console.log(title + ' -> output ' + v.out + ' (' + (path.length + 1) + ' symbols visited)');
console.log(' ' + path.join(' | ') + ' | STOP');
}
run('largest(12,25,7)', largest, { A: 12, B: 25, C: 7 }); run('largest(9,4,15)', largest, { A: 9, B: 4, C: 15 });
run('sum 1..n (n=4)', sumN, { n: 4 }); run('sum 1..n (n=0)', sumN, { n: 0 });আউটপুট আসে ৮ লাইনে। প্রথম জোড়া: largest(12,25,7) -> output 25 (6 symbols visited) আর পথ START | INPUT A,B,C | A>B? No | B>C? Yes | PRINT B | STOP — ঠিক ওপরের stepper-এর পথ। দ্বিতীয়টি output 15, পথ A>B? Yes | A>C? No | PRINT C. তৃতীয়টি sum 1..n (n=4) -> output 10 (14 symbols visited) — পথে i<=n? Yes চারবার, তারপর একবার No, অর্থাৎ লুপের তীর চারবার পেছনে ফিরেছে। শেষটি একটি edge case: n = 0 হলে শর্ত প্রথমবারেই মিথ্যা, লুপ একবারও চলে না, output 0. লক্ষ করুন, “ফ্লোচার্ট চালানো” মানে শুধু তীর ধরে হাঁটা — CPU-ও আসলে এভাবেই নির্দেশ থেকে নির্দেশে লাফ দেয় (পর্ব ২৪)।
৭ · প্রোগ্রামের তিন গঠন আর প্রোগ্রামিং পদ্ধতি
ওপরের ছয়টি উদাহরণ খেয়াল করুন — সবগুলো মাত্র তিন ধরনের গঠন দিয়ে তৈরি:
Sequence (ক্রম)
ধাপগুলো একটির পর একটি, কোনো শাখা ছাড়া। উদাহরণ ১।
Selection (নির্বাচন)
শর্ত অনুযায়ী দুই বা বেশি পথের একটি — IF … ELSE. উদাহরণ ২, ৩, ৬।
Repetition (পুনরাবৃত্তি)
শর্ত সত্য থাকা পর্যন্ত একই ধাপ বারবার — লুপ। উদাহরণ ৪, ৫।
১৯৬৬ সালে দুই ইতালীয় গবেষক Corrado Böhm আর Giuseppe Jacopini দেখান, যেকোনো গণনাযোগ্য সমস্যার প্রোগ্রাম শুধু এই তিন গঠন দিয়েই লেখা যায়। এর ওপর দাঁড়িয়ে আছে structured programming — যথেচ্ছ লাফ (goto) বাদ দিয়ে শুধু এই তিন গঠনে, ছোট ছোট অংশে (ফাংশনে) ভাগ করে প্রোগ্রাম লেখা। ফলে প্রোগ্রাম পড়া, পরীক্ষা করা আর বদলানো সহজ হয়। C ভাষায় এই তিন গঠন দেখবেন পর্ব ৩৯-এ (if, for, while), আর ফাংশনে ভাগ করা পর্ব ৪০-এ।
প্রোগ্রামিং প্যারাডাইম — ভাবার ভিন্ন ভিন্ন ধরন
একই সমস্যা নানা দৃষ্টিভঙ্গি থেকে সমাধান করা যায়; এই দৃষ্টিভঙ্গিকে বলে programming paradigm:
- Procedural: প্রোগ্রাম = ধাপের তালিকা আর ফাংশন। এই পর্বের সব উদাহরণ এই ধাঁচের। উদাহরণ: C, Pascal.
- Object-oriented (OOP): ডেটা আর তার ওপর কাজকে একসাথে “object”-এ রাখা — যেমন একটি “ব্যাংক হিসাব” object-এর ভেতরে ব্যালান্স আর “টাকা জমা” কাজ। উদাহরণ: Java, C++, Python.
- Functional: গণিতের ফাংশনের মতো — ইনপুট দিলে আউটপুট, ভেতরের মান না বদলিয়ে। উদাহরণ: Haskell; JavaScript আর Python-এও এই ধাঁচে লেখা যায়।
- Logic/declarative: শুধু তথ্য আর নিয়ম দিন, উত্তর কম্পিউটার খুঁজবে — Prolog, আর এক অর্থে SQL.
প্রথম ভাষা কোনটি?
HSC ICT-র সিলেবাসে প্রোগ্রামিং শেখানো হয় C দিয়ে, আর C মেমরি ও যন্ত্রকে কাছ থেকে দেখায় — তাই এই কোর্সের পর্ব ৩৯–৪০ C-তে। একেবারে নতুন, শুধু প্রোগ্রামিংয়ের স্বাদ নিতে চাইলে Python সবচেয়ে সহজ পাঠযোগ্য ভাষা; ওয়েব পেজকে প্রাণ দিতে চাইলে JavaScript. আসল কথা: প্রথম ভাষা যা-ই হোক, অ্যালগরিদম আর ফ্লোচার্টের চিন্তা সব ভাষায় একই। একটি ভাষা ভালোভাবে শিখলে দ্বিতীয়টি অনেক দ্রুত আসে।
পরীক্ষা ও ইন্টারভিউতে — এ ধরনের প্রশ্ন প্রায়ই আসে:
- Compiler আর interpreter-এর মূল পার্থক্য? compiler পুরো প্রোগ্রাম একবারে অনুবাদ করে object program বানায় আর সব ভুল একসাথে দেখায়; interpreter লাইন ধরে অনুবাদ করে চালায় আর প্রথম ভুলে থামে।
- ফ্লোচার্টে সিদ্ধান্তের প্রতীক কোনটি? রম্বস বা হীরক (◇); এ থেকে “হ্যাঁ” ও “না” দুটি পথ বের হয়।
- একটি ভালো অ্যালগরিদমের বৈশিষ্ট্য? ইনপুট, আউটপুট, সুনির্দিষ্টতা, সসীমতা আর কার্যকারিতা।
- 4GL-এর একটি উদাহরণ দিন। SQL — কী চাই বললেই হয়, কীভাবে খুঁজবে তা বলতে হয় না।
- Assembly ভাষাকে machine code-এ রূপান্তর করে কোন অনুবাদক? Assembler.
আরও গভীরে: সমস্যা ভাঙা আর অ্যালগরিদম ভাবার পদ্ধতি নিয়ে আমাদের C কোর্সের computational thinking পর্ব দেখুন; compiler, linker আর loader আসলে কী ফাইল বানায়, তা হাতে-কলমে আছে C toolchain পর্বে. interpreter-এ চলা ভাষা দিয়ে শুরু করতে চাইলে Python প্রোগ্রামিং কোর্স আছে; আর কোন অ্যালগরিদম কত দ্রুত, তা মাপার উপায় পাবেন C কোর্সের Big-O পর্বে.
৮ · AI-এর যুগে — অ্যালগরিদম আপনার, কোড AI-এর
আজ AI চ্যাটবট সাধারণ ভাষার বর্ণনা থেকে কোড লেখে, আবার Mermaid নামের লেখাভিত্তিক ভাষায় ফ্লোচার্টও এঁকে দেয়। কিন্তু AI শুধু আপনার বর্ণনার শব্দগুলো ধরে কাজ করে। বর্ণনা অস্পষ্ট হলে AI চুপচাপ একটি অনুমান বসিয়ে দেয় — আর সেটাই ভবিষ্যতের logic error. তাই কাজ ভাগ করুন: ধাপ আর শর্ত ঠিক করবেন আপনি, AI টাইপ করবে, আর পরীক্ষা করবেন আবার আপনি। বিশেষ করে edge case — শূন্য, ঋণাত্মক, সমান মান, খুব বড় সংখ্যা, 1900-এর মতো ব্যতিক্রম।
AI-এর আঁকা Mermaid ফ্লোচার্ট দেখতে এমন হয় (([ ]) = terminal, [/ /] = input/output, { } = decision, [ ] = process):
flowchart TD
S([শুরু]) --> I[/ইনপুট n/] --> P[sum = 0, i = 1] --> D{i <= n ?}
D -- হ্যাঁ --> L[sum = sum + i, i = i + 1] --> D
D -- না --> O[/প্রিন্ট sum/] --> E([শেষ])
AI প্রায়ই সিদ্ধান্তকে আয়তে এঁকে ফেলে, ইনপুটকে process-প্রতীকে রাখে, বা লুপের ফেরার তীর ভুল জায়গায় জোড়ে। পরীক্ষার খাতায় এমন ভুলে নম্বর কাটা যায়।
নিচের prompt-টি কপি করে নিজের সমস্যা বসিয়ে ব্যবহার করুন:
AI-এর উত্তর হাতে পেলে — যাচাইয়ের চেকলিস্ট
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিয়ে নিজে কিছুক্ষণ ভাবুন — তারপর “→ উত্তর” চাপুন। প্রোগ্রামিংয়ের ইতিহাসের সবচেয়ে বড় কিছু মোড় এই প্রশ্নগুলোর পেছনে।
প্র ০১যে যন্ত্র কখনো তৈরিই হয়নি, তার জন্য লেখা একটি অ্যালগরিদমকে কেন “প্রথম কম্পিউটার প্রোগ্রাম” বলা হয়? Ada Lovelace-এর Note G-তে কী ছিল?
১৮৩০-এর দশকে ইংরেজ গণিতবিদ Charles Babbage একটি যন্ত্রের নকশা করেন, যার নাম Analytical Engine. এতে ছিল আজকের কম্পিউটারের প্রায় সব মূল অংশ: হিসাবের অংশ (“mill”, আজকের CPU-র মতো), সংখ্যা রাখার অংশ (“store”, মেমরির মতো), আর পাঞ্চ কার্ডে নির্দেশ দেওয়ার ব্যবস্থা — জ্যাকার্ড তাঁতের কার্ড থেকে নেওয়া ধারণা। যন্ত্রটি শর্ত অনুযায়ী অন্য নির্দেশে যেতে আর ধাপ পুনরাবৃত্তি করতে পারত — অর্থাৎ selection আর repetition. অর্থ আর প্রযুক্তির অভাবে যন্ত্রটি কখনো সম্পূর্ণ তৈরি হয়নি।
ইতালীয় প্রকৌশলী Luigi Menabrea যন্ত্রটি নিয়ে ফরাসি ভাষায় একটি প্রবন্ধ লেখেন। Ada Lovelace (কবি Lord Byron-এর কন্যা, গণিতে প্রশিক্ষিত) ১৮৪৩ সালে সেটি ইংরেজিতে অনুবাদ করেন, আর সাথে জুড়ে দেন নিজের দীর্ঘ টীকা — Note A থেকে Note G, মূল প্রবন্ধের প্রায় তিন গুণ লম্বা। শেষ টীকা Note G-তে তিনি ধাপে ধাপে দেখান, Analytical Engine কীভাবে Bernoulli সংখ্যা নামের একটি জটিল সংখ্যাক্রম হিসাব করবে — কোন ধাপে কোন ঘরের মান কী হবে, কোন অংশ পুনরাবৃত্তি হবে, তার একটি টেবিলসহ। আজকের ভাষায় এটি একটি অ্যালগরিদম আর তার trace table — যন্ত্রের জন্য লেখা। এজন্যই তাঁকে প্রায়ই প্রথম প্রোগ্রামার বলা হয়। (Babbage নিজেও আগে কিছু ছোট উদাহরণ লিখেছিলেন, আর কাজে কার কতটা অবদান তা নিয়ে ইতিহাসবিদদের মধ্যে আলোচনা আছে; তবে প্রকাশিত, বিস্তারিত প্রথম উদাহরণ এটিই।)
Note G-এর চেয়েও দূরদর্শী ছিল Lovelace-এর আরেকটি চিন্তা: যন্ত্রটি শুধু সংখ্যা নয়, যেকোনো প্রতীক নিয়ে কাজ করতে পারবে — যেমন সংগীতের সুর, যদি সুরের নিয়ম প্রতীকে লেখা যায়। আবার তিনি সতর্কও করেন, যন্ত্রটি নিজে কিছু “সৃষ্টি” করে না; আমরা যা করতে বলি শুধু তা-ই করে। মার্কিন প্রতিরক্ষা বিভাগের জন্য তৈরি একটি প্রোগ্রামিং ভাষার নাম রাখা হয় তাঁর নামে — Ada (প্রথম মান প্রকাশিত হয় ১৯৮০ সালে)।
মূল উপলব্ধি: অ্যালগরিদম যন্ত্রের চেয়ে পুরোনো আর স্বাধীন। যন্ত্র না থাকলেও নিখুঁত ধাপ লেখা যায়, আর সেই ধাপের সঠিকতা হাতে trace করেই যাচাই করা যায় — ঠিক যেমন আপনি এই পর্বে কাগজে-কলমে dry run করলেন।
প্র ০২“Algorithm” শব্দটি এসেছে নবম শতকের বাগদাদের এক গণিতবিদের নাম থেকে। একজন মানুষের নাম কীভাবে কম্পিউটার বিজ্ঞানের মূল শব্দ হলো?
নবম শতকে আব্বাসীয় খলিফাদের রাজধানী বাগদাদে ছিল “বাইতুল হিকমা” (House of Wisdom) — গ্রিক, ভারতীয় আর পারস্যের জ্ঞান অনুবাদ ও চর্চার কেন্দ্র। সেখানে কাজ করতেন Muhammad ibn Musa al-Khwarizmi (আনুমানিক ৭৮০–৮৫০), যাঁর নামের শেষাংশ এসেছে মধ্য এশিয়ার খোয়ারিজম অঞ্চল থেকে।
তাঁর দুটি বই ইতিহাস বদলে দেয়। একটি বইয়ে তিনি ভারতীয় সংখ্যা-পদ্ধতি — শূন্যসহ দশটি অঙ্ক আর স্থানীয় মান — দিয়ে যোগ, বিয়োগ, গুণ, ভাগের নিয়ম ধাপে ধাপে ব্যাখ্যা করেন। দ্বাদশ শতকে বইটির লাতিন অনুবাদ শুরু হয় “Algoritmi de numero Indorum” কথা দিয়ে — “ভারতীয় সংখ্যা সম্পর্কে al-Khwarizmi বলেন”। ইউরোপে তাঁর নামের লাতিন রূপ “Algoritmi” থেকে আসে “algorism” — নতুন অঙ্কে হিসাবের পদ্ধতি; পরে বানান বদলে “algorithm”, অর্থ দাঁড়ায় যেকোনো ধাপে ধাপে হিসাবের পদ্ধতি। তাঁর আরেকটি বই “al-Kitab al-mukhtasar fi hisab al-jabr wal-muqabala”-র “al-jabr” শব্দ থেকেই “algebra”.
মজার ব্যাপার, ধাপে ধাপে হিসাবের পদ্ধতি তাঁর চেয়েও পুরোনো। প্রায় খ্রিস্টপূর্ব ৩০০ সালে গ্রিক গণিতবিদ Euclid দুটি সংখ্যার গসাগু বের করার যে পদ্ধতি লিখেছিলেন (বড়টিকে ছোটটি দিয়ে ভাগ করুন, ভাগশেষ দিয়ে আবার ভাগ করুন, ভাগশেষ 0 হলে থামুন), সেটিকে প্রায়ই সবচেয়ে পুরোনো পরিচিত অ্যালগরিদমগুলোর একটি বলা হয় — আর এতে আছে লুপ, শর্ত আর নিশ্চিত থামার নিয়ম। বিংশ শতকে Alan Turing আর Alonzo Church “অ্যালগরিদম” ধারণাটিকে গাণিতিকভাবে সংজ্ঞায়িত করেন, আর Donald Knuth তাঁর বিখ্যাত বই “The Art of Computer Programming”-এ এই পর্বে দেখা পাঁচ বৈশিষ্ট্য তালিকা করেন।
মূল উপলব্ধি: আমরা কাগজে যোগ-গুণ করতে যে নিয়ম মানি, সেটাই অ্যালগরিদমের আদি রূপ। কম্পিউটার নতুন কিছু আবিষ্কার করেনি — হাজার বছরের পুরোনো ধাপে ধাপে ভাবার পদ্ধতিকে কোটি গুণ দ্রুত করেছে।
প্র ০৩১৯৪৭ সালে একটি কম্পিউটারের ভেতরে সত্যিকারের পোকা পাওয়া গিয়েছিল। “bug” আর “compiler” — দুটি শব্দের সাথেই Grace Hopper-এর নাম জড়িয়ে আছে কেন?
Grace Hopper ছিলেন মার্কিন নৌবাহিনীর গণিতবিদ, পরে রিয়ার অ্যাডমিরাল। দ্বিতীয় বিশ্বযুদ্ধের সময় থেকে তিনি Harvard-এর Mark I আর Mark II কম্পিউটারে কাজ করেন। ১৯৪৭ সালের ৯ সেপ্টেম্বর Mark II-এর একটি relay-তে (বিদ্যুতে চলা যান্ত্রিক সুইচ) আটকে থাকা একটি মথ (পোকা) খুঁজে পান দলের সদস্যরা। তাঁরা পোকাটি লগবুকে টেপ দিয়ে লাগিয়ে লেখেন: “First actual case of bug being found.” লগবুকের পাতাটি আজ Smithsonian জাদুঘরে আছে।
লক্ষ করুন “actual” শব্দটি — অর্থাৎ “bug” মানে যন্ত্রের ত্রুটি, এই কথাটি আগে থেকেই প্রচলিত ছিল; উনিশ শতকে Thomas Edison-ও তাঁর চিঠিতে যান্ত্রিক সমস্যাকে “bug” বলেছেন। তাই পোকাটি শব্দটির জন্ম দেয়নি, তবে গল্পটি Hopper বারবার বলতেন বলে এটি বিখ্যাত হয়ে যায়। পোকাটি তিনি নিজে খুঁজে পাননি বলেই ইতিহাসবিদদের মত।
Hopper-এর আসল বিপ্লব অন্যখানে। ১৯৫০-এর দশকের শুরুতে প্রোগ্রাম লেখা হতো machine code বা assembly-তে, আর বেশিরভাগ মানুষ বিশ্বাস করতেন কম্পিউটার শুধু হিসাব করতে পারে, প্রোগ্রাম লিখতে পারে না। ১৯৫২ সালে UNIVAC I কম্পিউটারের জন্য Hopper তৈরি করেন A-0 System — যা আগে থেকে লিখে রাখা subroutine-গুলো কোড অনুযায়ী খুঁজে এনে জোড়া দিয়ে একটি পূর্ণ machine প্রোগ্রাম বানাত। তিনি এর নাম দেন “compiler” (সংকলক)। আজকের মাপে A-0 একটি compiler-এর চেয়ে linker-loader-এর বেশি কাছাকাছি, তবু প্রোগ্রাম দিয়ে প্রোগ্রাম বানানোর ধারণাটি এখান থেকেই জনপ্রিয় হয়। পরে তাঁর FLOW-MATIC ভাষা ইংরেজির মতো শব্দে লেখা যেত, আর সেই অভিজ্ঞতা থেকে ১৯৫৯ সালে তৈরি হয় ব্যবসার ভাষা COBOL — যা আজও বহু ব্যাংকের পুরোনো সিস্টেমে চলে।
মূল উপলব্ধি: অনুবাদক-প্রোগ্রামের ধারণা প্রথমে অবিশ্বাস্য মনে হয়েছিল। Hopper দেখিয়েছিলেন, মানুষকে যন্ত্রের ভাষা শেখানোর চেয়ে অনুবাদক-প্রোগ্রাম দিয়ে যন্ত্রকে মানুষের ভাষার কাছাকাছি আনা বেশি শক্তিশালী।
প্র ০৪১৯৫০-এর দশকে অনেক প্রোগ্রামার বিশ্বাস করতেন, compiler-এর বানানো কোড হাতে লেখা কোডের সমান দ্রুত কখনো হবে না। FORTRAN কীভাবে এই ধারণা ভাঙল?
১৯৫৩ সালে IBM-এর তরুণ প্রোগ্রামার John Backus তাঁর ঊর্ধ্বতনদের কাছে একটি প্রস্তাব দেন: IBM 704 কম্পিউটারের জন্য এমন একটি ভাষা, যাতে বিজ্ঞানী আর প্রকৌশলীরা গণিতের সূত্রের মতো করে প্রোগ্রাম লিখতে পারবেন। কারণ ছিল অর্থনৈতিক — তখন একটি কম্পিউটার চালানোর খরচের বড় অংশ যেত প্রোগ্রামারদের বেতন আর ভুল খোঁজায়। ১৯৫৪ সাল থেকে তাঁর ছোট দল কাজ শুরু করে, আর ১৯৫৭ সালে প্রকাশিত হয় FORTRAN (FORmula TRANslation) compiler.
বড় বাধা ছিল সন্দেহ। অভিজ্ঞ প্রোগ্রামাররা নিজেদের হাতে লেখা assembly নিয়ে গর্বিত ছিলেন, আর আগের কিছু “স্বয়ংক্রিয় প্রোগ্রামিং” ব্যবস্থা খুব ধীর কোড বানাত। Backus বুঝেছিলেন, compiler-এর কোড হাতে লেখা কোডের প্রায় সমান দ্রুত না হলে কেউ ব্যবহার করবে না। তাই তাঁর দল সবচেয়ে বেশি পরিশ্রম করে optimization-এ — লুপ বিশ্লেষণ, রেজিস্টারের বুদ্ধিমান ব্যবহার। ফল ছিল চমকপ্রদ: অনেক ক্ষেত্রে FORTRAN-এর কোড দক্ষ প্রোগ্রামারের হাতে লেখা কোডের কাছাকাছি গতিতে চলত, অথচ প্রোগ্রাম লিখতে লাগত অনেক কম লাইন আর সময়।
FORTRAN-কে প্রায়ই প্রথম ব্যাপকভাবে ব্যবহৃত high-level ভাষা বলা হয়। এটি প্রমাণ করে দেয় যে 3GL বাস্তবে কাজ করে, আর এর পরেই আসে COBOL (১৯৫৯), LISP, ALGOL. ভাষার ব্যাকরণ নিখুঁতভাবে লেখার জন্য Backus পরে যে পদ্ধতি দেন, তা আজ BNF (Backus–Naur Form) নামে compiler তৈরির মূল হাতিয়ার। ১৯৭৭ সালে তিনি Turing Award পান। আর FORTRAN হারিয়ে যায়নি — আধুনিক সংস্করণে আবহাওয়ার পূর্বাভাস আর বৈজ্ঞানিক সুপারকম্পিউটারে আজও এর বিপুল ব্যবহার।
মূল উপলব্ধি: নতুন বিমূর্ততার তলা (high-level ভাষা) টিকে থাকে তখনই, যখন তার দাম — গতি বা মেমরির ক্ষতি — যথেষ্ট কম হয়। FORTRAN জিতেছিল কারণ এর compiler নিখুঁতভাবে কাজ করেছিল; AI কোডিং টুলকেও একই পরীক্ষায় উতরাতে হচ্ছে।
প্র ০৫১৯৬৮ সালে Edsger Dijkstra লিখলেন, “Go To Statement Considered Harmful”. একটি সাধারণ লাফের নির্দেশ কেন এত বিতর্কের জন্ম দিল, আর structured programming কী বদলাল?
প্রথম দিকের ভাষাগুলোতে (FORTRAN, BASIC) প্রোগ্রামের প্রবাহ নিয়ন্ত্রণের প্রধান উপায় ছিল GOTO — “অমুক লাইনে লাফ দাও”। assembly-র jump নির্দেশেরই সরাসরি রূপ। ছোট প্রোগ্রামে এটি সহজ, কিন্তু বড় প্রোগ্রামে শত শত GOTO এদিক-ওদিক লাফ দিত; ফ্লোচার্ট আঁকলে তীরগুলো সুতার জটের মতো দেখাত — একে ঠাট্টা করে বলা হতো “spaghetti code”. কোনো একটি লাইনে পৌঁছানোর আগে প্রোগ্রাম কোন কোন পথ ঘুরে এসেছে, তা বোঝা প্রায় অসম্ভব হয়ে যেত।
১৯৬৬ সালে Böhm আর Jacopini গাণিতিকভাবে দেখান, sequence, selection আর repetition — এই তিন গঠনই যেকোনো প্রোগ্রামের জন্য যথেষ্ট; GOTO অপরিহার্য নয়। ১৯৬৮ সালের মার্চে ডাচ বিজ্ঞানী Edsger W. Dijkstra Communications of the ACM পত্রিকায় একটি ছোট চিঠি লেখেন। তাঁর যুক্তি: প্রোগ্রাম লেখা হয় স্থির লেখা হিসেবে, কিন্তু চলে সময়ের ভেতর দিয়ে; ভালো প্রোগ্রামে এই দুইয়ের মিল যত স্পষ্ট, প্রোগ্রাম বোঝা আর প্রমাণ করা তত সহজ — আর যথেচ্ছ GOTO সেই মিল নষ্ট করে। চিঠির বিখ্যাত শিরোনামটি দিয়েছিলেন পত্রিকার সম্পাদক Niklaus Wirth, যিনি পরে Pascal ভাষা তৈরি করেন — structured programming শেখানোর জন্যই।
বিতর্ক সহজে থামেনি। ১৯৭৪ সালে Donald Knuth “Structured Programming with go to Statements” প্রবন্ধে দেখান, কিছু ক্ষেত্রে সাবধানী GOTO কোডকে আরও পরিষ্কার করে। আজকের সমাধান মাঝামাঝি: Python আর Java-তে GOTO নেই, কিন্তু লুপ থেকে বের হতে break আছে; C-তে goto এখনো আছে, আর Linux kernel-এর মতো বড় প্রকল্পে ভুল হলে পরিষ্কারের জন্য নিয়ন্ত্রিতভাবে ব্যবহার হয়। Dijkstra ১৯৭২ সালে Turing Award পান।
মূল উপলব্ধি: ভালো প্রোগ্রাম শুধু সঠিক ফল দেয় না, মানুষের পড়া ও যাচাইয়ের উপযোগীও হয়। আপনার ফ্লোচার্টের তীরগুলো যত সরল আর একমুখী, প্রোগ্রামে ভুল লুকানোর জায়গা তত কম।
অনুশীলন
প্রথম তিনটি খাতা-কলমেই চলবে। শেষটিতে ওপরের ফ্লোচার্ট-যন্ত্রের কোড একটু বদলাতে হবে।
-
ধনাত্মক, ঋণাত্মক না শূন্য? একটি সংখ্যা N ইনপুট নিয়ে সেটি ধনাত্মক, ঋণাত্মক না শূন্য তা জানানোর অ্যালগরিদম আর সিউডোকোড লিখুন। ফ্লোচার্টে কয়টি সিদ্ধান্ত-প্রতীক লাগবে?
অ্যালগরিদম: ধাপ ১: শুরু। ধাপ ২: N ইনপুট নাও। ধাপ ৩: N > 0 হলে “ধনাত্মক” প্রিন্ট করে ধাপ ৫-এ যাও। ধাপ ৪: N < 0 হলে “ঋণাত্মক”, না হলে “শূন্য” প্রিন্ট করো। ধাপ ৫: শেষ।
সিউডোকোড:
IF N > 0 THEN PRINT "ধনাত্মক" ELSE IF N < 0 THEN PRINT "ঋণাত্মক" ELSE PRINT "শূন্য". ফ্লোচার্টে দুটি রম্বস লাগে — তিনটি ফলের জন্য দুটি হ্যাঁ/না প্রশ্নই যথেষ্ট। শূন্যকে ভুলে গেলে (শুধু “> 0 না হলে ঋণাত্মক”) 0-কে ঋণাত্মক বলবে — একটি logic error. -
ভুলের ধরন চিনুন: (ক)
int x = 5— সেমিকোলন নেই; (খ) আয়তক্ষেত্রের ক্ষেত্রফলarea = 2 * (l + w);; (গ) ব্যবহারকারী শূন্য দিলেavg = total / count;; (ঘ)pritnf("Hello");.(ক) syntax error — compiler আগেই ধরবে। (খ) logic error — এটি পরিসীমার সূত্র; প্রোগ্রাম চলবে কিন্তু ভুল ফল দেবে, ঠিক হবে
l * w. (গ) runtime error — count = 0 হলে শূন্য দিয়ে ভাগ, শুধু নির্দিষ্ট ইনপুটে ঘটে। (ঘ) বানান ভুল — compile-এর সময় ধরা পড়ে (C-তে অজানা ফাংশন হিসেবে, শেষে linker-ও আপত্তি করে), তাই এটিকে syntax/compile-time error হিসেবেই ধরা হয়। -
Dry run: উদাহরণ ৫-এর ফ্যাক্টোরিয়ালের সিউডোকোড n = 5 দিয়ে চালান। প্রতিটি পাকে i আর fact-এর মান trace table-এ লিখুন। শুরুতে
fact ← 0লিখলে কী হতো?শুরু: i = 1, fact = 1. পাক ১: fact = 1, i = 2. পাক ২: fact = 2, i = 3. পাক ৩: fact = 6, i = 4. পাক ৪: fact = 24, i = 5. পাক ৫: fact = 120, i = 6. শর্ত 6 ≤ 5 মিথ্যা — আউটপুট 120.
fact ← 0দিলে প্রতিটি গুণফল 0 — আউটপুট 0. প্রোগ্রাম কোনো সতর্কবার্তা ছাড়াই চলবে: একটি নিখুঁত logic error. নিয়ম মনে রাখুন: যোগফলের শুরু 0, গুণফলের শুরু 1. -
ফ্লোচার্ট-যন্ত্রে edge case: ওপরের কোডে
largest-কে A = 7, B = 7, C = 3 আর A = 5, B = 5, C = 5 দিয়ে চালান (একটিrun(...)লাইন যোগ করুন)। কোন পথ নেয়, আর উত্তর কি ঠিক? তারপর ফ্যাক্টোরিয়ালের জন্যsumN-এর মতো একটিfactNবানান।(7, 7, 3):
A>B? No | B>C? Yes | PRINT B→ 7, ঠিক। (5, 5, 5):A>B? No | B>C? No | PRINT C→ 5, এটিও ঠিক — সমান হলে যেকোনোটি প্রিন্ট করলেই মান একই। কিন্তু প্রশ্ন যদি হয় “কোন ভ্যারিয়েবলটি বড়”, তবে সমান মানের জন্য আলাদা নিয়ম ঠিক করতে হবে — এটাই সমস্যা বিশ্লেষণের কাজ।factN:sumNকপি করে P0-তেv.fact = 1; v.i = 1;, P1-এv.fact *= v.i; v.i++;, আর O-তেv.out = v.fact.{ n: 5 }দিলে output 120, আর{ n: 0 }দিলে 1 — 0! = 1, তাই এই edge case-ও ঠিক।
নিজেকে যাচাই করুন
ভুল হলে কারণসহ ব্যাখ্যা পাবেন, আবার চেষ্টাও করতে পারবেন।
ক্রমপ্রোগ্রাম তৈরির ধাপগুলো সঠিক ক্রমে সাজান (▲▼ চেপে সরান)
- 🔍 সমস্যা বিশ্লেষণ
- 🧠 অ্যালগরিদম তৈরি
- 🔷 ফ্লোচার্ট বা সিউডোকোড
- ⌨️ কোডিং
- 🐞 Compile, পরীক্ষা আর debugging
- 📄 ডকুমেন্টেশন ও রক্ষণাবেক্ষণ
Assembly ভাষায় লেখা প্রোগ্রামকে machine code-এ রূপান্তর করে কোন অনুবাদক প্রোগ্রাম?
- Compiler
- Interpreter
- Assembler
- Loader
ফ্লোচার্টে শর্ত যাচাই বা সিদ্ধান্তের (হ্যাঁ/না) জন্য কোন প্রতীক ব্যবহার করা হয়?
- আয়তক্ষেত্র
- রম্বস (হীরক আকৃতি)
- সামান্তরিক
- ডিম্বাকার
SQL কোন প্রজন্মের প্রোগ্রামিং ভাষার উদাহরণ?
- প্রথম প্রজন্ম (1GL)
- দ্বিতীয় প্রজন্ম (2GL)
- তৃতীয় প্রজন্ম (3GL)
- চতুর্থ প্রজন্ম (4GL)
একটি প্রোগ্রাম কোনো error ছাড়াই চলে, কিন্তু 10 আর 20-এর গড় দেখায় 20, কারণ লেখা হয়েছে avg = a + b / 2. এটি কোন ধরনের ভুল?
- Logic error
- Syntax error
- Runtime error
- Linker error
Interpreter সম্পর্কে কোন কথাটি সঠিক?
- এটি পুরো প্রোগ্রামের একটি object program তৈরি করে
- এটি লাইন ধরে অনুবাদ করে চালায় এবং প্রথম ভুলের লাইনে থেমে যায়
- একবার অনুবাদের পর প্রোগ্রাম চালাতে আর interpreter লাগে না
- এটির প্রোগ্রাম সবসময় compiler-এর প্রোগ্রামের চেয়ে দ্রুত চলে
নিচের কোনটি একটি সঠিক অ্যালগরিদমের আবশ্যিক বৈশিষ্ট্য নয়?
- সসীম সংখ্যক ধাপে শেষ হওয়া
- প্রতিটি ধাপ স্পষ্ট ও দ্ব্যর্থহীন হওয়া
- একটি নির্দিষ্ট প্রোগ্রামিং ভাষায় লেখা হওয়া
- অন্তত একটি আউটপুট দেওয়া
শব্দকোষ
লেখার মধ্যে ডটেড দাগ দেওয়া শব্দে মাউস রাখুন বা চাপুন — অর্থ দেখাবে। এই পর্বের সব নতুন শব্দ এখানে একসাথে:
মনে রাখুন
- প্রোগ্রাম = নিখুঁত ধাপের তালিকা। আগে অ্যালগরিদম, তারপর ফ্লোচার্ট বা সিউডোকোড, শেষে কোড।
- প্রজন্ম: 1GL machine, 2GL assembly (দুটিই low-level, যন্ত্রনির্ভর), 3GL C/Python/Java, 4GL SQL, 5GL Prolog/স্বাভাবিক ভাষা।
- অনুবাদক: assembler (assembly → machine), compiler (পুরোটা একবারে, দ্রুত চলে, সব ভুল একসাথে), interpreter (লাইন ধরে, প্রথম ভুলে থামে); Java = bytecode + JVM. linker জোড়ে, loader RAM-এ তোলে।
- ভুল তিন রকম: syntax (ব্যাকরণ), logic (ভুল ফল), runtime (চলার মাঝে আটকে যাওয়া)। dry run আর edge case দিয়ে পরীক্ষা করুন।
- ফ্লোচার্ট: ডিম্বাকার = শুরু/শেষ, সামান্তরিক = ইনপুট/আউটপুট, আয়ত = প্রক্রিয়া, রম্বস = সিদ্ধান্ত। সব প্রোগ্রাম তিন গঠনে: sequence, selection, repetition.
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- পর্ব ৩৯ · C প্রোগ্রামিং — ভ্যারিয়েবল, শর্ত আর লুপপরবর্তী পর্বএই পর্বের অ্যালগরিদমগুলো C কোডে।
- পর্ব ৩৭ · HTML-এ লিংক, ছবি, টেবিল আর ফর্মআগের পর্বওয়েব পেজের গঠন — যা প্রোগ্রাম নয়, markup.
- পর্ব ২৩ · ট্রানজিস্টর থেকে অ্যাপ — বিমূর্ততার স্তরফিরে দেখুনmachine code থেকে high-level ভাষা পর্যন্ত তলাগুলো।
- কম্পিউটার ফান্ডামেন্টালস ও ICT · কোর্স হোম৫৫টি পর্বপুরো কোর্সের রোডম্যাপ — কোন পর্ব কখন।
- C প্রোগ্রামিংগভীরে যানcompiler, debugging আর অ্যালগরিদমের পূর্ণ কোর্স।
- Python প্রোগ্রামিংপাশের ট্র্যাকinterpreter-এ চলা সবচেয়ে সহজপাঠ্য ভাষা দিয়ে শুরু।