Computational Thinking & Mathematical Reasoning
প্রোগ্রামারের মতো চিন্তা করা শিখুন
1. The Mistake Most Beginners Make
Most beginners open the code editor and start typing. Then they get stuck. Then they Google. Then they copy-paste. Then the program almost works. Then they give up.
Professional programmers do the opposite: they think first, code last. Before writing a single line, they break down the problem, pick a strategy, check that the strategy is correct, and only then begin typing.
কোর্সের নিয়ম: কোনো বন্ধুকে সহজ ভাষায় নিজের algorithm বোঝাতে না পারলে কোড লেখা শুরু করবেন না।
2. The Four Pillars of Computational Thinking
Computer scientist Jeannette Wing summed up programmer-thinking in four mental moves. Every time you solve a problem, you use them — consciously or not.
বড় একটি সমস্যাকে ছোট, সমাধানযোগ্য অংশে ভাগ করা।
আগের সমস্যার সাথে মিল খুঁজে বের করা।
অপ্রয়োজনীয় বিস্তারিত বাদ দিয়ে শুধু গুরুত্বপূর্ণটি রাখা।
ধাপে ধাপে একটি পরিষ্কার সমাধান লেখা।
3. What Is an Algorithm, Really?
An algorithm is a finite sequence of unambiguous instructions that, given valid input, produces the correct output in finite time. It has five required properties:
- Finiteness — must end after finitely many steps. (নির্দিষ্ট ধাপে শেষ হতে হবে)
- Definiteness — every step is precise and unambiguous. (প্রতিটি ধাপ স্পষ্ট)
- Input — takes zero or more valid inputs.
- Output — produces one or more outputs.
- Effectiveness — each step is doable by a machine in finite time.
ALGORITHM make_tea:
1. Boil water in a pot.
2. Add tea leaves and sugar.
3. Wait 3 minutes.
4. Add milk.
5. Strain into a cup.
6. Serve.
This looks informal, but it is a real algorithm. Every property above holds.
4. Pseudocode — The Language of Thinking
Pseudocode is half-English, half-programming. You can express the logic without worrying about semicolons or braces. Then translate it into real code.
ALGORITHM find_max(A, n):
max ← A[0]
FOR i FROM 1 TO n - 1:
IF A[i] > max:
max ← A[i]
RETURN max
Now the same idea in real C. You can run it right here:
#include <stdio.h>
int find_max(int A[], int n) {
int max = A[0];
for (int i = 1; i < n; i++) {
if (A[i] > max) max = A[i];
}
return max;
}
int main(void) {
int A[] = {18, 7, 42, 3, 25, 9};
int n = sizeof(A) / sizeof(A[0]);
printf("Maximum = %d\n", find_max(A, n));
return 0;
}
5. Flowcharts — Thinking in Shapes
A flowchart draws an algorithm visually. Rectangles are actions, diamonds are decisions, arrows show the flow. Drawing a flowchart is often the fastest way to untangle a hard problem.
Here is the same logic as runnable C code:
#include <stdio.h>
int main(void) {
int x;
scanf("%d", &x);
if (x > 0) printf("Positive\n");
else if (x < 0) printf("Negative\n");
else printf("Zero\n");
return 0;
}
6. Loop Invariants — The Secret of Correctness
A loop invariant is a statement that remains true before the loop, after every iteration, and still true when the loop ends. It is the single most powerful tool for proving that code is correct.
(2) Show: if it holds before iteration k, it still holds after iteration k.
(3) Combine with the termination condition to conclude correctness.
(১) লুপ শুরুর আগে invariant সত্য প্রমাণ করুন।
(২) প্রমাণ করুন: iteration k-এর আগে সত্য থাকলে, k-এর পরেও সত্য থাকে।
(৩) Termination শর্তের সাথে মিলিয়ে চূড়ান্ত শুদ্ধতা প্রমাণ করুন।
Example: For find_max above, the invariant is — "At the start of iteration i, max equals the maximum of A[0..i-1]."
- Before loop (i = 1): max = A[0]. Maximum of A[0..0] is A[0] itself. ✓
- Step: if A[i] > max, we update max to A[i]. So max = maximum of A[0..i]. ✓
- After loop (i = n): max = maximum of A[0..n-1] — which is our answer. ✓
7. Mathematical Induction — Recursion's Twin
Mathematical induction proves a statement P(n) holds for all natural numbers n by two steps:
- Base case: Prove P(0) or P(1).
- Inductive step: Assume P(k). Prove P(k + 1).
Verify it with code — Gauss's formula vs. a direct loop:
#include <stdio.h>
int main(void) {
int n = 100;
// Method 1 — direct loop
long sum_loop = 0;
for (int i = 1; i <= n; i++) sum_loop += i;
// Method 2 — Gauss's formula
long sum_formula = (long)n * (n + 1) / 2;
printf("Sum by loop = %ld\n", sum_loop);
printf("Sum by formula = %ld\n", sum_formula);
printf("Match: %s\n", sum_loop == sum_formula ? "YES" : "NO");
return 0;
}
8. Decomposition in Practice — A Real Problem
Problem: Given a list of exam scores, find the average of the top 3.
সমস্যা: একটি পরীক্ষার স্কোরের তালিকা থেকে সর্বোচ্চ ৩টি স্কোরের গড় বের করতে হবে।
Beginner reaction: "just write some code". Professional reaction: decompose first.
Step 1 — What do I need?
input : array of scores, length n
output : a single number = average of top 3
Step 2 — Break into subproblems
(a) sort the array in descending order
(b) take the first 3 elements
(c) compute the average
Step 3 — Have I solved these before?
- sorting → yes (qsort library function)
- pick first 3 → trivial indexing
- average → sum / 3
Once decomposed, coding is almost mechanical:
#include <stdio.h>
#include <stdlib.h>
int cmp_desc(const void *a, const void *b) {
return *(const int*)b - *(const int*)a;
}
int main(void) {
int scores[] = {72, 98, 65, 90, 54, 88, 77};
int n = sizeof(scores) / sizeof(scores[0]);
qsort(scores, n, sizeof(int), cmp_desc);
double avg = (scores[0] + scores[1] + scores[2]) / 3.0;
printf("Top 3: %d, %d, %d\n", scores[0], scores[1], scores[2]);
printf("Average of top 3 = %.2f\n", avg);
return 0;
}
9. Abstraction — The Mental Superpower
When you call printf, you do not care how the bytes reach your terminal. You just call it.
That is abstraction: hiding irrelevant detail behind a clean interface.
printf কল করার সময় আপনি জানেন না byte গুলো আসলে কীভাবে terminal-এ পৌঁছায় — আপনি শুধু ফাংশনটিই কল করেন। এটিই abstraction: অপ্রয়োজনীয় বিস্তারিত লুকিয়ে রেখে একটি পরিষ্কার interface প্রদান করা।
| Layer | Deals with | Hides from you |
|---|---|---|
| Your C code | Logic, data | — |
printf | Formatting | How bytes are written |
| C standard library | System calls | Syscall numbers |
| OS kernel | Hardware drivers | Port numbers, interrupts |
| CPU | Instructions | Transistors, silicon |
10. Practice Problems
-
Write pseudocode to reverse an array of integers in place, without using a second array.একটি int array কে in-place (দ্বিতীয় array ছাড়াই) reverse করার pseudocode লিখুন।
✨ Show Answer (উত্তর দেখুন)
ALGORITHM reverse(A, n): i ← 0 j ← n - 1 WHILE i < j: swap(A[i], A[j]) i ← i + 1 j ← j - 1Now the runnable C version:
reverse.c#include <stdio.h> void reverse(int A[], int n) { int i = 0, j = n - 1; while (i < j) { int t = A[i]; A[i] = A[j]; A[j] = t; i++; j--; } } int main(void) { int A[] = {1, 2, 3, 4, 5}; int n = 5; reverse(A, n); for (int i = 0; i < n; i++) printf("%d ", A[i]); printf("\n"); return 0; } -
Write a C program that solves FizzBuzz for N = 15 — print "Fizz" for multiples of 3, "Buzz" for 5, "FizzBuzz" for both, else the number.N = 15 পর্যন্ত FizzBuzz সমাধান করুন — ৩-এর গুণিতক হলে "Fizz", ৫-এর গুণিতক হলে "Buzz", দুটোই হলে "FizzBuzz", নতুবা সংখ্যাটি প্রিন্ট করুন।
✨ Show Answer (উত্তর দেখুন)
fizzbuzz.c#include <stdio.h> int main(void) { for (int i = 1; i <= 15; i++) { if (i % 15 == 0) printf("FizzBuzz\n"); else if (i % 3 == 0) printf("Fizz\n"); else if (i % 5 == 0) printf("Buzz\n"); else printf("%d\n", i); } return 0; } -
For the function that computes the sum of an array, state a loop invariant and argue briefly why it holds.একটি array-র যোগফল বের করার ফাংশনের জন্য একটি loop invariant লিখুন এবং ব্যাখ্যা করুন কেন এটি সত্য থাকে।
✨ Show Answer (উত্তর দেখুন)
Invariant: At the start of iteration i, the variable
sequalsA[0] + A[1] + ... + A[i-1].Why it holds: Before the loop (i = 0), s = 0, which is the empty sum — true. In each step we add A[i] and increment i, so after the step s becomes A[0] + ... + A[i]. When i = n, s equals the total sum.
Invariant: iteration i-এর শুরুতে
s-এর মান সমানA[0] + A[1] + ... + A[i-1]।
কেন সত্য: লুপের শুরুতে (i = 0) s = 0 — শূন্য যোগফল, সত্য। প্রতিটি iteration-এ A[i] যোগ হয় এবং i বাড়ে, ফলে iteration শেষে s = A[0] + ... + A[i]। সবশেষে i = n হলে s পুরো array-র যোগফল হবে। -
Prove by induction that 2⁰ + 2¹ + ... + 2ⁿ = 2ⁿ⁺¹ − 1.Induction ব্যবহার করে প্রমাণ করুন: 2⁰ + 2¹ + ... + 2ⁿ = 2ⁿ⁺¹ − 1।
✨ Show Answer (উত্তর দেখুন)
Base (n = 0): Left side = 2⁰ = 1. Right side = 2¹ − 1 = 1. ✓
Inductive step: Assume it holds for some k ≥ 0, i.e., 2⁰ + 2¹ + ... + 2ᵏ = 2ᵏ⁺¹ − 1. Then for k + 1:
2⁰ + 2¹ + ... + 2ᵏ + 2ᵏ⁺¹ = (2ᵏ⁺¹ − 1) + 2ᵏ⁺¹ (by hypothesis) = 2 · 2ᵏ⁺¹ − 1 = 2ᵏ⁺² − 1 ✓Verify with code:
pow2_sum.c#include <stdio.h> int main(void) { long sum = 0, pow = 1; int n = 10; for (int i = 0; i <= n; i++) { sum += pow; pow *= 2; } printf("2^0 + ... + 2^%d = %ld\n", n, sum); printf("Formula 2^%d - 1 = %ld\n", n + 1, pow - 1); return 0; } -
You already know how to find the maximum of an array. How would you reuse that pattern to find the second maximum?আপনি ইতিমধ্যে array-র maximum বের করা জানেন। একই pattern ব্যবহার করে দ্বিতীয় সর্বোচ্চ মান কীভাবে বের করবেন?
✨ Show Answer (উত্তর দেখুন)
Keep two variables —
maxandsecond. Walk the array once: when a new element beatsmax, pushmaxintosecondand updatemax. If it is only bigger thansecondbut notmax, updatesecond.দুটি variable রাখুন —
maxওsecond। Array একবার স্ক্যান করুন: কোনো মানmax-এর চেয়ে বড় হলে পুরনোmax-কেsecond-এ সরিয়ে নতুন মানকেmaxবানান। মানটি যদি শুধুsecond-এর চেয়ে বড় হয় কিন্তুmax-এর চেয়ে ছোট, তাহলেsecondআপডেট করুন।second_max.c#include <stdio.h> #include <limits.h> int main(void) { int A[] = {18, 7, 42, 3, 25, 42, 9}; int n = sizeof(A) / sizeof(A[0]); int max = INT_MIN, second = INT_MIN; for (int i = 0; i < n; i++) { if (A[i] > max) { second = max; max = A[i]; } else if (A[i] > second && A[i] < max) { second = A[i]; } } printf("Max = %d, Second max = %d\n", max, second); return 0; } -
Describe your mobile phone as a stack of at least 4 abstraction layers, from hardware to apps.আপনার মোবাইল ফোনকে কমপক্ষে ৪টি abstraction স্তরে ভাগ করে দেখান — hardware থেকে app পর্যন্ত।
✨ Show Answer (উত্তর দেখুন)
One reasonable answer:
- Hardware — CPU, RAM, screen, battery.
- Firmware / drivers — talks to each hardware component.
- Operating System (Android / iOS) — manages processes, memory, files.
- Frameworks — provide UI widgets, networking APIs.
- Apps (WhatsApp, Facebook, etc.) — what you actually see.
উপরের প্রতিটি স্তর নিচের স্তরের বিস্তারিত লুকিয়ে রেখে একটি পরিষ্কার interface দেয় — এটিই abstraction।
-
You want the GPA across 40 courses. Break the problem into 4 or more subproblems (decomposition).৪০টি কোর্সের GPA হিসাব করতে চান। সমস্যাটিকে ৪টি বা তার বেশি উপ-সমস্যায় ভাগ করুন।
✨ Show Answer (উত্তর দেখুন)
- Read each course's grade and credit hour (input).
- Convert each letter grade to a grade point (e.g., A = 4.00, A− = 3.70, …).
- For each course, compute (grade point × credit).
- Sum those values to get total quality points.
- Sum credits to get total credit hours.
- GPA = total quality points ÷ total credit hours.
প্রতিটি ছোট ধাপ আলাদাভাবে সহজ — সমস্যাটিকে এভাবে ভাঙলে সমাধান পরিষ্কার হয়ে যায়।
-
Check each of the 5 algorithm properties (finiteness, definiteness, input, output, effectiveness) on the "make tea" procedure. Fix any that fail.আপনার চা বানানোর পদ্ধতির ওপর algorithm-এর ৫টি বৈশিষ্ট্য (finiteness, definiteness, input, output, effectiveness) যাচাই করুন। যেকোনো ফাঁক থাকলে ঠিক করুন।
✨ Show Answer (উত্তর দেখুন)
Finiteness: yes — 6 steps. Definiteness: weak — "wait 3 minutes" is OK, but "add sugar" should say how much. Fix: "add 2 teaspoons of sugar". Input: implicit — water, tea leaves, sugar, milk. Fix: state them explicitly. Output: yes — a cup of tea. Effectiveness: yes — every step is doable.
সবগুলো পরীক্ষা করলেই বোঝা যায় যে ছোট ছোট সংশোধন করলে চা বানানোর পদ্ধতিটিও একটি সম্পূর্ণ algorithm হয়ে ওঠে।
Glossary (শব্দকোষ)
| Term | Meaning | বাংলায় |
|---|---|---|
| Algorithm | A finite, unambiguous sequence of steps that solves a problem. | সসীম ও সুনির্দিষ্ট ধাপের ক্রম, যা একটি সমস্যা সমাধান করে। |
| Computational Thinking | The mental discipline of formulating problems so that a computer can solve them. | সমস্যাকে এমনভাবে সাজানো, যাতে কম্পিউটার সেটি সমাধান করতে পারে। |
| Decomposition | Breaking a big problem into smaller, manageable parts. | বড় সমস্যাকে ছোট অংশে ভেঙে ফেলা। |
| Pattern Recognition | Spotting similarities between problems you have already solved. | আগে সমাধান করা সমস্যার সাথে মিল খুঁজে বের করা। |
| Abstraction | Hiding unimportant detail to focus on the essence. | অপ্রয়োজনীয় বিস্তার আড়াল করে মূল ধারণায় মনোযোগ দেওয়া। |
| Pseudocode | Plain-language description of an algorithm — half English, half code. | অ্যালগরিদমের সাধারণ ভাষায় বর্ণনা — অর্ধেক ইংরেজি, অর্ধেক কোড। |
| Flowchart | A diagram of an algorithm using boxes and arrows. | বক্স ও অ্যারো দিয়ে অ্যালগরিদমের চিত্র। |
| Loop Invariant | A condition that is true before and after every iteration of a loop. | প্রতিটি iteration-এর আগে ও পরে যে শর্ত সত্য থাকে। |
| Induction | Proof technique: prove a base case, then prove each step from the previous. | প্রমাণের কৌশল — base case প্রমাণ করে ধাপে ধাপে এগোনো। |
| Trace Table | A table that records the value of each variable at each step. | প্রতিটি ধাপে variable-এর মান রেকর্ড করার টেবিল। |
Summary — Module 02
Programming is thinking first, typing last. The four pillars — decomposition, pattern recognition, abstraction, algorithmic thinking — are your mental toolkit. Pseudocode and flowcharts are your scratch pad. Loop invariants and induction are your proof tools. Internalize these and C becomes just a language for writing down what you already figured out.