Solved AP Papers — Combined 5 Bank 2023, Bangladesh Bank 2023, Combined 5 Bank 2024 (all BIBM)
BIBM-এর তিনটি Assistant Programmer লিখিত পরীক্ষার সব টেকনিক্যাল প্রশ্নের পূর্ণ মডেল উত্তর এখানে দেওয়া হলো। গণিত, ইংরেজি, অনুবাদ ও Focus Writing-এর সমাধান আলাদা অধ্যায়ে আছে। প্রশ্নগুলো পরীক্ষার্থীদের স্মৃতি থেকে সংকলিত, তাই কিছু জায়গায় ভাষা অসম্পূর্ণ ছিল। সেসব জায়গায় যে ব্যাখ্যা ধরে নেওয়া হয়েছে, তা উত্তরেই স্পষ্ট লেখা আছে।
১.১Combined 5 Bank — Assistant Programmer (০৩.০২.২০২৩)
| তথ্য | বিবরণ |
|---|---|
| তারিখ | ০৩.০২.২০২৩ |
| প্রশ্নকর্তা | BIBM |
| ধরন | ৮০ MCQ (IT ৭৫ + গণিত ও GK ২৫); লিখিত ২০০ = IT ১৫০ + গণিত ৪টি (২০) + Focus ১০ + অনুবাদ B/E ২০ |
| টপিক | Heap, SQL join, UML class diagram, Function Point, array function, TLS, CRC, graph representation, browser security, LRU |
Extract-Root: root (সর্বোচ্চ মান) ফেরত দিন। শেষ উপাদানটি root-এ এনে sift-down করুন, অর্থাৎ বড় child-এর সঙ্গে swap (children: 2i+1, 2i+2)।
| ধাপ | অপারেশন | কী ঘটে | Heap (array) | ফেরত |
|---|---|---|---|---|
| a | Insert 5 | খালি heap, 5 root হয় | [5] | — |
| b | Insert 6 | 6 শেষে বসে; parent 5 < 6, তাই swap | [6, 5] | — |
| c | Insert 8 | index 2-এ বসে; parent 6 < 8, তাই swap | [8, 5, 6] | — |
| d | Extract-Root | 8 বের হয়; শেষের 6 root-এ আসে; child 5 < 6, তাই কিছু বদলায় না | [6, 5] | 8 |
| e | Insert 4 | index 2-এ বসে; parent 6 > 4, তাই ঠিক আছে | [6, 5, 4] | — |
| f | Insert 11 | index 3-এ বসে; parent 5-এর সঙ্গে swap, তারপর root 6-এর সঙ্গে swap | [11, 6, 4, 5] | — |
| g | Extract-Root | 11 বের হয়; 5 root-এ আসে; বড় child 6-এর সঙ্গে swap | [6, 5, 4] | 11 |
| h | Insert 7 | index 3-এ বসে; parent 5-এর সঙ্গে swap, তারপর root 6-এর সঙ্গে swap | [7, 6, 4, 5] | — |
| i | Extract-Root | 7 বের হয়; 5 root-এ আসে; বড় child 6-এর সঙ্গে swap | [6, 5, 4] | 7 |
| j | Extract-Root | 6 বের হয়; 4 root-এ আসে; child 5 > 4, তাই swap | [5, 4] | 6 |
উত্তর: Extract-Root অপারেশনগুলো ক্রমানুসারে 8, 11, 7, 6 ফেরত দেয়। শেষে heap-এ থাকে [5, 4]।
যুক্তি: একটি S-record ও একটি U-record তখনই সম্পর্কিত, যখন একটি সাধারণ T-record (tid) থাকে, যেখানে R-এ (sid, tid) আছে এবং Q-তে (tid, uid) আছে। তাই R ও Q-কে tid-এর ওপর join করতে হবে।
-- সংক্ষিপ্ত রূপ (R.sid ও Q.uid foreign key, তাই S ও U join না করলেও চলে)
SELECT R.sid, Q.uid
FROM R
JOIN Q ON R.tid = Q.tid;
-- পূর্ণ রূপ (S ও U-তে সত্যিই record আছে কিনা তাও নিশ্চিত করে)
SELECT S.sid, U.uid
FROM S
JOIN R ON S.sid = R.sid
JOIN Q ON R.tid = Q.tid
JOIN U ON Q.uid = U.uid;
"Composed of" মানে Composition (ভরাট diamond ◆)। অংশটি সম্পূর্ণের বাইরে আলাদাভাবে টিকে থাকে না: বই মুছে ফেললে তার part, chapter ও section-ও মুছে যায়। Multiplicity হলো সম্পূর্ণের দিকে 1 এবং অংশের দিকে 1..* ("several")।
ব্যাখ্যা লিখুন: (১) চারটি class এবং প্রতিটির attribute; (২) সম্পর্কগুলো composition, কারণ chapter কেবল একটি part-এর ভেতরেই থাকে; (৩) প্রতিটি সম্পর্কের multiplicity 1 → 1..*। চাইলে operation যোগ করতে পারেন, যেমন Book.addPart() বা Chapter.getSections()।
ধাপ ১: FP = 180 × 0.87 = 156.6
ধাপ ২: ধরে নিচ্ছি "performance factor 4" মানে productivity, অর্থাৎ ৪ FP প্রতি person-day।
Effort = 156.6 ÷ 4 = 39.15 ≈ 40 person-days
লজিক: প্রথম উপাদানকে min ধরুন। বাকি উপাদানগুলোর ওপর একবার লুপ চালান; কোনোটি min-এর চেয়ে ছোট হলে min আপডেট করুন। Time O(n), extra space O(1)।
/* C */
#include <stdio.h>
int findMin(int arr[], int n) {
int min = arr[0];
for (int i = 1; i < n; i++)
if (arr[i] < min)
min = arr[i];
return min;
}
int main(void) {
int a[] = {34, -7, 19, 0, 8};
int n = sizeof(a) / sizeof(a[0]);
printf("Smallest = %d\n", findMin(a, n));
return 0;
}
/* Output: Smallest = -7 */
// Java
public class MinFinder {
static int findMin(int[] arr) {
if (arr == null || arr.length == 0)
throw new IllegalArgumentException("empty");
int min = arr[0];
for (int i = 1; i < arr.length; i++)
if (arr[i] < min) min = arr[i];
return min;
}
public static void main(String[] args) {
int[] a = {34, -7, 19, 0, 8};
System.out.println("Smallest = " + findMin(a));
}
}
// Output: Smallest = -7
C-তে array পাঠালে আসলে pointer যায়, তাই size (n) আলাদা parameter হিসেবে পাঠাতে হয়। Java-তে arr.length থেকে size পাওয়া যায়।
সার্ভারের certificate-এ যে public key আছে, তার জোড়া private key দিয়েই সার্ভার প্রমাণ করে "আমিই আসল সাইট"। এই key চুরি হলে আক্রমণকারী যা করতে পারে:
- সার্ভারের ছদ্মবেশ (Impersonation): আসল ও বৈধ certificate-সহ একটি ভুয়া সাইট চালাতে পারে। DNS spoofing, ARP spoofing বা ভুয়া Wi-Fi-এর মাধ্যমে ব্যবহারকারীকে সেখানে নিলে ব্রাউজার কোনো সতর্কবার্তা দেখাবে না।
- Active Man-in-the-Middle: ক্লায়েন্ট ও আসল সার্ভারের মাঝে বসে উভয় দিকের TLS সংযোগ নিজেই শেষ (terminate) করতে পারে। এতে password, OTP, কার্ড নম্বর পড়তে পারে, এবং লেনদেনের পরিমাণ বা গন্তব্য অ্যাকাউন্ট বদলে দিতে পারে।
- রেকর্ড করা ট্রাফিক ডিক্রিপ্ট করা (passive): সার্ভার RSA key exchange ব্যবহার করলে (TLS 1.2-এর non-forward-secret cipher suite) session key ক্লায়েন্টের পাঠানো premaster secret থেকে আসে, যা ওই public key দিয়ে এনক্রিপ্ট করা। তাই আগে রেকর্ড করা এবং ভবিষ্যতের সব সেশন ডিক্রিপ্ট করা যায়।
(EC)DHE (Forward Secrecy, TLS 1.3-এ বাধ্যতামূলক) ব্যবহার হলে private key কেবল handshake-এ signing-এর কাজে লাগে। তখন অতীতের রেকর্ড করা ট্রাফিক ডিক্রিপ্ট করা যায় না, তবে active MitM (পয়েন্ট ২) তখনও সম্ভব। - সার্ভারের নামে সই করা: একই key দিয়ে অন্য কিছুতে (যেমন code বা message) সই হয়ে থাকলে আক্রমণকারী সার্ভারের নামে জাল সই তৈরি করতে পারে।
| প্রতিরোধ ও প্রতিকার | কেন |
|---|---|
| Certificate অবিলম্বে revoke করা (CRL/OCSP) ও নতুন key pair তৈরি করা | চুরি হওয়া key দিয়ে আর বিশ্বাসযোগ্যতা পাওয়া যাবে না |
| শুধু ECDHE/TLS 1.3 চালু রাখা | Forward secrecy নিশ্চিত হয় |
| Private key HSM-এ রাখা | Key HSM থেকে বের করা যায় না |
| Certificate Transparency monitoring | ভুয়া certificate ধরা পড়ে |
| কম মেয়াদের certificate, নিয়মিত key rotation | চুরি হলেও ক্ষতির সময়সীমা কম থাকে |
Generator-এ ১১টি বিট আছে, তাই এর degree r = 11 − 1 = 10 (CRC remainder ১০ বিটের)।
| Burst length L | Detection probability |
|---|---|
| L ≤ r | ১০০% (সব ধরা পড়ে) |
| L = r + 1 | 1 − (1/2)r−1 |
| L > r + 1 | 1 − (1/2)r |
এখানে L = 10 এবং r = 10, তাই L ≤ r। Generator-এর সর্বোচ্চ ও সর্বনিম্ন (x0) বিট দুটিই 1, তাই সব burst error ধরা পড়বে; detection probability = 1 (100%)।
তুলনার জন্য: L = 11 হলে probability = 1 − 1/29 ≈ 0.998; L ≥ 12 হলে 1 − 1/210 ≈ 0.999।
| বিষয় | Adjacency List | Adjacency Matrix |
|---|---|---|
| Space | O(V + E): sparse graph-এ ভালো | O(V²) |
| u-এর সব neighbour বের করা | O(out-degree(u)) | O(V), পুরো row স্ক্যান করতে হয় |
| (u, v) edge আছে কিনা | O(out-degree(u)) | O(1) |
| BFS / DFS | O(V + E) | O(V²) |
| In-degree বের করা | O(V + E) | O(V), একটি column |
List-এ দ্রুত: ১০ লক্ষ নোড ও ৫০ লক্ষ edge-এর একটি sparse graph-এ (যেমন ব্যাংক গ্রাহকের লেনদেন নেটওয়ার্ক) BFS/DFS দিয়ে সব reachable নোড বের করা, বা প্রতিটি নোডের out-degree গোনা। List-এ এতে O(V + E) সময় লাগে, matrix-এ O(V²)।
Matrix-এ দ্রুত: "u থেকে v-তে সরাসরি edge আছে কিনা" বারবার জিজ্ঞাসা করা (O(1) lookup), dense graph-এ Floyd–Warshall all-pairs shortest path, অথবা কোনো vertex universal sink কিনা (in-degree V−1, out-degree 0) তা O(V) সময়ে বের করা।
এটি ব্রাউজারের frame navigation policy নিয়ে প্রশ্ন। বর্তমান ব্রাউজার Descendant Policy মেনে চলে: একটি frame কেবল তার নিজের ভেতরের (descendant) frame-কে অন্য URL-এ নিতে পারে।
- Pixel delegation-এর যুক্তি: B যদি A-এর display area-র ভেতরে থাকে, তাহলে স্ক্রিনের ওই অংশটি A-রই দেওয়া। A চাইলে এমনিতেই ওই জায়গায় নিজের কনটেন্ট দেখাতে, B-কে সরিয়ে দিতে বা ওপরে কিছু বসাতে পারে। তাই B-কে অন্য origin-এ পাঠানোর অনুমতি দিলে A-এর নতুন কোনো ক্ষমতা যোগ হয় না, আর নিরাপত্তাও কমে না।
- Same-Origin Policy অক্ষত থাকে: Navigation করলে A, B-এর DOM, cookie বা ডেটা পড়তে পারে না; শুধু B-এর জায়গায় কী লোড হবে তা ঠিক করে। তাই confidentiality ভাঙে না।
- উদার নীতির ঝুঁকি: যেকোনো frame যেকোনো frame-কে navigate করতে পারলে (permissive policy) একটি আক্রমণকারী frame অন্য সাইটের ভেতরের login বা payment frame-কে ভুয়া পেজে পাঠিয়ে দিতে পারত (frame hijacking / Guninski attack)। ব্যবহারকারী ঠিকানা দেখে আসল সাইট ভাবত, অথচ তথ্য যেত আক্রমণকারীর কাছে।
- তাই সীমারেখা: "যার স্ক্রিন, তার নিয়ন্ত্রণ।" A কেবল নিজের এলাকার ভেতরের frame বদলাতে পারে। পাশের বা ওপরের অন্য origin-এর frame বদলাতে পারে না।
LRU (Least Recently Used) নিয়মে page fault হলে, সবচেয়ে বেশি সময় ধরে ব্যবহার হয়নি এমন page সরানো হয়। F = fault, H = hit।
| Ref | 1 | 2 | 3 | 4 | 2 | 3 | 4 | 1 | 2 | 1 | 1 | 3 | 1 | 4 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Frame 1 | 1 | 1 | 1 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 4 | 3 | 3 | 3 |
| Frame 2 | – | 2 | 2 | 2 | 2 | 2 | 2 | 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| Frame 3 | – | – | 3 | 3 | 3 | 3 | 3 | 3 | 2 | 2 | 2 | 2 | 2 | 4 |
| F/H | F | F | F | F | H | H | H | F | F | H | H | F | H | F |
সরানোর সিদ্ধান্ত:
- Ref 4-এ সবচেয়ে পুরোনো 1, তাই 1 সরে।
- Ref 1 (৮ম)-এ ক্রম 2, 3, 4 (২ সবচেয়ে পুরোনো), তাই 2 সরে।
- Ref 2 (৯ম)-এ ক্রম 3, 4, 1, তাই 3 সরে।
- Ref 3 (১২তম)-এ ক্রম 4, 2, 1, তাই 4 সরে।
- Ref 4 (১৪তম)-এ ক্রম 2, 3, 1, তাই 2 সরে।
উত্তর: Page faults = 8, hits = 6; fault rate = 8/14 ≈ 57%।
১.২Bangladesh Bank — Assistant Programmer (০৩.০২.২০২৩)
| তথ্য | বিবরণ |
|---|---|
| তারিখ | ০৩.০২.২০২৩ (১ ঘণ্টা MCQ + ২ ঘণ্টা লিখিত) |
| প্রশ্নকর্তা | BIBM |
| ধরন | ৮০ MCQ; লিখিত = ৯টি subjective (১৫০) + গণিত ৪টি (২০) + Focus (১০) + অনুবাদ B/E (২০) |
| টপিক | Hashing, graph representation, LCM program, SQL, UML, overriding/hiding, CIA ও E2E encryption, Diffie-Hellman MitM |
| Key | h(k) = k mod 13 | Probe sequence | Final slot |
|---|---|---|---|
| 10 | 10 | 10 খালি | 10 |
| 3 | 3 | 3 খালি | 3 |
| 5 | 5 | 5 খালি | 5 |
| 6 | 6 | 6 খালি | 6 |
| 16 | 3 | 3 (3 দিয়ে ভরা) → 4 খালি | 4 |
| 17 | 4 | 4 (16) → 5 (5) → 6 (6) → 7 খালি | 7 |
| 19 | 6 | 6 (6) → 7 (17) → 8 খালি | 8 |
| Index | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Key | – | – | – | 3 | 16 | 5 | 6 | 17 | 19 | – | 10 | – | – |
মোট collision: 16-এ ১টি, 17-এ ৩টি, 19-এ ২টি, মোট ৬টি। Index 3 থেকে 8 পর্যন্ত একটানা ভরা অংশটি primary clustering-এর উদাহরণ, যা linear probing-এর প্রধান দুর্বলতা। এর প্রতিকার হলো quadratic probing বা double hashing। Load factor α = 7/13 ≈ 0.54।
Binary heap-এর মতো নম্বর দিলে vertex i-এর children হয় 2i ও 2i+1, আর parent হয় ⌊i/2⌋। Tree-কে undirected graph ধরা হলো।
Adjacency List
1 → 2 → 3
2 → 1 → 4 → 5
3 → 1 → 6 → 7
4 → 2
5 → 2
6 → 3
7 → 3
Directed (parent → child) হিসেবে ধরলে: 1→2,3; 2→4,5; 3→6,7; এবং 4–7-এর list খালি।
Adjacency Matrix (symmetric)
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
|---|---|---|---|---|---|---|---|
| 1 | 0 | 1 | 1 | 0 | 0 | 0 | 0 |
| 2 | 1 | 0 | 0 | 1 | 1 | 0 | 0 |
| 3 | 1 | 0 | 0 | 0 | 0 | 1 | 1 |
| 4 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
| 5 | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
| 6 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
| 7 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
Edge সংখ্যা = V − 1 = 6। List-এ মোট entry ২ × 6 = 12, matrix-এ cell 7 × 7 = 49, যার মাত্র 12টি 1। Tree sparse, তাই এখানে list বেশি সাশ্রয়ী।
Overflow এড়াতে (a / gcd) * b ক্রমে হিসাব করুন। এতে আগে ভাগ হয়, তারপর গুণ।
/* C */
#include <stdio.h>
#include <stdlib.h>
long long gcd(long long a, long long b) {
while (b != 0) {
long long t = a % b;
a = b;
b = t;
}
return a;
}
int main(void) {
long long a, b;
printf("Enter A and B: ");
scanf("%lld %lld", &a, &b);
a = llabs(a); b = llabs(b);
if (a == 0 || b == 0) {
printf("LCM = 0\n");
return 0;
}
long long lcm = (a / gcd(a, b)) * b;
printf("LCM = %lld\n", lcm);
return 0;
}
/* Input: 12 18 -> LCM = 36 */
// Java
import java.util.Scanner;
public class LCM {
static long gcd(long a, long b) {
while (b != 0) {
long t = a % b;
a = b;
b = t;
}
return a;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long a = Math.abs(sc.nextLong());
long b = Math.abs(sc.nextLong());
long lcm = (a == 0 || b == 0) ? 0
: (a / gcd(a, b)) * b;
System.out.println("LCM = " + lcm);
}
}
// Input: 12 18 -> LCM = 36
Trace (12, 18): gcd(12, 18) → gcd(18, 12) → gcd(12, 6) → gcd(6, 0) = 6; LCM = 12/6 × 18 = 36। Time complexity O(log min(A, B))।
যুক্তি: "Romantic comedy" মানে একই movie-র দুটি genre আছে: Romance এবং Comedy। প্রতিটি genre HasGenre-এ আলাদা সারিতে থাকে, তাই দুটি শর্ত একই সারিতে মেলানো যায় না।
-- পদ্ধতি ১: GROUP BY + HAVING (সবচেয়ে পরিষ্কার)
SELECT COUNT(*) AS romantic_comedy_count
FROM (
SELECT hg.mid
FROM HasGenre hg
JOIN Genres g ON g.gid = hg.gid
WHERE g.genre IN ('Romance', 'Comedy')
GROUP BY hg.mid
HAVING COUNT(DISTINCT g.genre) = 2
) AS rc;
-- পদ্ধতি ২: দুটি IN subquery
SELECT COUNT(*) AS romantic_comedy_count
FROM Movies m
WHERE m.mid IN (SELECT hg.mid FROM HasGenre hg JOIN Genres g ON g.gid = hg.gid
WHERE g.genre = 'Romance')
AND m.mid IN (SELECT hg.mid FROM HasGenre hg JOIN Genres g ON g.gid = hg.gid
WHERE g.genre = 'Comedy');
WHERE genre = 'Romance' AND genre = 'Comedy' লিখলে সবসময় 0 আসে, কারণ এক সারির genre একসাথে দুটি মান হতে পারে না। আবার OR লিখলে শুধু romance বা শুধু comedy movie-ও গোনা হয়। যদি ডেটাবেসে "Romantic Comedy" নামে একটিমাত্র genre থাকে, তাহলে সহজ WHERE g.genre = 'Romantic Comedy' দিয়েই হবে। উত্তরে এই অনুমানটি উল্লেখ করুন।
| বাক্য | মডেলে কী |
|---|---|
| "LAN consists of nodes; circular configuration" | LAN ◆— Node, composition, multiplicity 1 → 2..*; ring গঠন হয় self-association দিয়ে |
| "Every node has a unique name and refers to its next node" | Node-এ name {unique}; self-association next, multiplicity 1 |
| "Different kinds of nodes" | Node একটি abstract superclass; Workstation, Server ও Printer তার subclass (generalization) |
| "Workstations are originators of messages" | Workstation 1 —originates→ 0..* Packet |
| "Servers and printers can receive messages" | Server ও Printer-এ receive(p: Packet) operation |
| "Packets contain originator, destination and content" | Packet-এর attribute বা association: originator (Workstation), destination (Node), content |
public class A {
public void m1() {}
public void m2() {}
public void m3(int i) {}
public void m4(String i) {}
}
public class B extends A {
public static void m1() {}
public void m2() {}
public void m3(int i) {}
public static void m4(String i) {}
}| ধারণা | শর্ত | কখন resolve হয় |
|---|---|---|
| Overloading | একই নাম, ভিন্ন parameter list (একই বা subclass-এ) | Compile time |
| Overriding | Subclass-এ একই signature-এর instance method; parent-এর method-ও instance | Runtime (dynamic dispatch) |
| Hiding | Parent ও child দুজনেরই static method, একই signature | Compile time (reference type দেখে) |
| Method | A-তে | B-তে | ফল |
|---|---|---|---|
| m1() | instance | static | Compile error: "m1() in B cannot override m1() in A; overriding method is static"। Static method দিয়ে instance method লুকানো যায় না। |
| m2() | instance | instance, একই signature | Overridden |
| m3(int) | instance | instance, একই signature | Overridden |
| m4(String) | instance | static | Compile error (m1-এর একই কারণে) |
উপসংহার: m2 ও m3 overridden। m1 ও m4 compile হবে না, তাই এখানে কোনো hiding ঘটে না। কোনো method-এর parameter list ভিন্ন নয়, তাই কোনো overloading-ও নেই। এছাড়া কোডে দুটি সমস্যা ঠিক করতে হবে: extends a হবে extends A, আর একটি .java ফাইলে দুটি public class থাকতে পারে না, তাই দুটি আলাদা ফাইলে রাখতে হবে।
Hiding ও overloading কখন হতো: A-এর m1 যদি public static void m1() হতো, তাহলে B-এর static m1() সেটিকে hide করত। B-তে যদি public void m3(double d) থাকত, তাহলে সেটি A-এর m3(int)-এর overload হতো।
class A {
public static void s() { System.out.println("A.s"); }
public void m() { System.out.println("A.m"); }
}
class B extends A {
public static void s() { System.out.println("B.s"); } // hiding
@Override public void m(){ System.out.println("B.m"); } // overriding
public void m(int x) { System.out.println("B.m(int)"); } // overloading
}
public class Demo {
public static void main(String[] args) {
A ref = new B();
ref.m(); // B.m : runtime-এ object-এর type (B) দেখে
ref.s(); // A.s : compile time-এ reference-এর type (A) দেখে, অর্থাৎ hiding
}
}
CIA Triad:
- Confidentiality: অননুমোদিত কেউ তথ্য পড়তে পারবে না।
- Integrity: তথ্য অননুমোদিতভাবে বদলানো যাবে না।
- Availability: অনুমোদিত ব্যবহারকারী প্রয়োজনের সময় তথ্য পাবে।
End-to-end encryption (E2EE) মূলত confidentiality ও (MAC বা AEAD ব্যবহার করলে) integrity নিশ্চিত করে।
উত্তর: Application Layer (Layer 7)।
| লেয়ার | উদাহরণ | E2E কি? | খরচ ও রক্ষণাবেক্ষণ |
|---|---|---|---|
| Network (L3) | IPsec | না; host-to-host বা gateway-to-gateway সুরক্ষা দেয়, ব্যবহারকারী-থেকে-ব্যবহারকারী নয় | OS ও router কনফিগার করতে হয়; বিশেষজ্ঞ লাগে |
| Transport (L4) | TLS | না; প্রতিটি hop-এ (সার্ভার, proxy, load balancer) ডিক্রিপ্ট হয়, সার্ভার plaintext দেখে | সহজ, কিন্তু উদ্দেশ্য পূরণ হয় না |
| Application (L7) | Signal Protocol, PGP, libsodium | হ্যাঁ; কেবল প্রেরক ও প্রাপকের অ্যাপের কাছে key থাকে | প্রস্তুত লাইব্রেরি, নেটওয়ার্ক অবকাঠামো বদলাতে হয় না |
কারণ:
- Development time: পরীক্ষিত লাইব্রেরি (OpenSSL, libsodium, Bouncy Castle) সরাসরি অ্যাপের কোডে ব্যবহার করা যায়। Kernel বা নেটওয়ার্ক ডিভাইসে হাত দিতে হয় না।
- Maintainability: এনক্রিপশন লজিক অ্যাপের ভেতরেই থাকে। নেটওয়ার্ক, ক্লাউড প্রোভাইডার বা ISP বদলালেও কিছু পরিবর্তন করতে হয় না, এবং আপডেট সাধারণ সফটওয়্যার রিলিজের মতো দেওয়া যায়।
- Development cost: বিশেষ হার্ডওয়্যার (VPN concentrator) বা প্রতিটি router কনফিগারেশনের খরচ লাগে না।
- প্রকৃত end-to-end: একমাত্র এই লেয়ারেই মাঝের সার্ভার, এমনকি কোম্পানির নিজের সার্ভারও, ডেটা পড়তে পারে না। ফলে ডেটা লিক হলেও confidentiality বজায় থাকে।
সীমাবদ্ধতা: প্রতিটি অ্যাপে আলাদাভাবে বাস্তবায়ন করতে হয় এবং key management (key exchange, backup) সাবধানে ডিজাইন করতে হয়। বাস্তবে Application-layer E2EE-র নিচে TLS-ও রাখা হয় (defense in depth)।
মূল দুর্বলতা: সাধারণ Diffie-Hellman-এ authentication নেই। কেউ যাচাই করে না যে প্রাপ্ত public key আসলে অপর পক্ষেরই। প্রকাশ্য মান: prime q ও primitive root α।
আক্রমণের ধাপ (আক্রমণকারী Darth, Stallings-এর বিবরণ অনুযায়ী):
- Darth দুটি private key XD1 ও XD2 বেছে নেয় এবং সংশ্লিষ্ট public key হিসাব করে: YD1 = αXD1 mod q, YD2 = αXD2 mod q।
- Alice, Bob-কে YA পাঠায়। Darth সেটি আটকে দিয়ে Bob-কে YD1 পাঠায়, এবং নিজে হিসাব করে K2 = YAXD2 mod q।
- Bob, YD1 পেয়ে হিসাব করে K1 = YD1XB mod q।
- Bob, Alice-কে YB পাঠায়। Darth সেটি আটকে দিয়ে Alice-কে YD2 পাঠায়, এবং হিসাব করে K1 = YBXD1 mod q।
- Alice, YD2 পেয়ে হিসাব করে K2 = YD2XA mod q।
ফল: Alice ও Darth একই key K2 পায়, আর Bob ও Darth একই key K1 পায়। Alice ও Bob ভাবে তারা নিজেদের মধ্যে একটি গোপন key ভাগ করেছে। Darth প্রতিটি বার্তা ডিক্রিপ্ট করে পড়তে বা বদলাতে পারে, তারপর আবার এনক্রিপ্ট করে সামনে পাঠায়।
Darth: XD1 = 3 → YD1 = 125 mod 23 = 10 | XD2 = 7 → YD2 = 57 mod 23 = 17
Alice: K2 = 176 mod 23 = 12 | Darth: K2 = 87 mod 23 = 12 ✔
Bob: K1 = 1015 mod 23 = 5 | Darth: K1 = 193 mod 23 = 5 ✔
আক্রমণ না থাকলে Alice ও Bob একই key পেত: 196 mod 23 = 815 mod 23 = 2।
প্রতিরোধ:
- Public key-কে authenticate করা: digital signature বা certificate-সহ DH (Station-to-Station protocol, TLS-এর signed ECDHE)।
- বাইরের কোনো চ্যানেলে key fingerprint মিলিয়ে দেখা (যেমন Signal-এর safety number)।
- Pre-shared key বা PKI ব্যবহার করা।
১.৩Combined 5 Bank (Job ID 10198) — Assistant Programmer (০৯.০২.২০২৪)
| তথ্য | বিবরণ |
|---|---|
| ব্যাংক | Sonali Bank, BKB, Karmasangsthan Bank, ICB প্রমুখ |
| তারিখ | ০৯.০২.২০২৪ (১ ঘণ্টা MCQ + ২ ঘণ্টা লিখিত) |
| প্রশ্নকর্তা | BIBM |
| ধরন | ৮০ MCQ (IT ৫০ + গণিত ও GK ২০); লিখিত = ১০টি subjective (১৫০) + গণিত ৪টি (২০) + Focus (২০) + Letter (১০) |
| বৈশিষ্ট্য | প্রোগ্রামিং-প্রধান: ৩টি প্রোগ্রাম লেখা, ১টি output নির্ণয়, ৩টি SQL, এরপর তত্ত্ব ও নিজের প্রজেক্ট নিয়ে প্রশ্ন |
লজিক: x prime হবে যদি x ≥ 2 হয় এবং 2 থেকে √x পর্যন্ত কোনো সংখ্যা দিয়ে x বিভাজ্য না হয়। লুপের শর্ত d * d <= x লিখলে sqrt function লাগে না। প্রতিটি সংখ্যার জন্য O(√x), মোট O(n√n)। বড় n-এর জন্য Sieve of Eratosthenes দ্রুততর: O(n log log n)।
/* C */
#include <stdio.h>
int isPrime(int x) {
if (x < 2) return 0;
for (int d = 2; d * d <= x; d++)
if (x % d == 0) return 0;
return 1;
}
int main(void) {
int n;
printf("Enter n: ");
scanf("%d", &n);
printf("Primes between 1 and %d:\n", n);
for (int i = 2; i <= n; i++)
if (isPrime(i))
printf("%d ", i);
printf("\n");
return 0;
}
// Java
import java.util.Scanner;
public class Primes {
static boolean isPrime(int x) {
if (x < 2) return false;
for (int d = 2; d * d <= x; d++)
if (x % d == 0) return false;
return true;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter n: ");
int n = sc.nextInt();
for (int i = 2; i <= n; i++)
if (isPrime(i))
System.out.print(i + " ");
System.out.println();
}
}
Sample: Enter n: 30 → 2 3 5 7 11 13 17 19 23 29। 1 prime নয়, তাই লুপ 2 থেকে শুরু।
Pattern: পাশাপাশি পদের পার্থক্য 1, 2, 3, 4, …। তাই প্রতিটি পদ আগের পদের সঙ্গে k যোগ করে পাওয়া যায় (k = 1, 2, 3, …)।
যাচাই: t5 = 1 + 5·4/2 = 11 ✔; S5 = 5 + 4·5·6/6 = 5 + 20 = 25 = 1 + 2 + 4 + 7 + 11 ✔
/* C */
#include <stdio.h>
int main(void) {
int n;
long long term = 1, sum = 0;
printf("Enter n: ");
scanf("%d", &n);
for (int k = 1; k <= n; k++) {
printf("%lld%s", term, k < n ? " + " : "");
sum += term;
term += k; /* next term = term + k */
}
printf("\nSum = %lld\n", sum);
return 0;
}
// Java
import java.util.Scanner;
public class SeriesSum {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter n: ");
int n = sc.nextInt();
long term = 1, sum = 0;
for (int k = 1; k <= n; k++) {
System.out.print(term + (k < n ? " + " : ""));
sum += term;
term += k;
}
System.out.println("\nSum = " + sum);
// closed form check:
long f = n + (long)(n - 1) * n * (n + 1) / 6;
System.out.println("Formula = " + f);
}
}
Sample: n = 5 → 1 + 2 + 4 + 7 + 11, Sum = 25। n = 7 হলে পদগুলো 16 ও 22 পর্যন্ত যায়, Sum = 63 (সূত্রে 7 + 6·7·8/6 = 63 ✔)।
1
01
101
0101
10101Pattern বিশ্লেষণ: i-তম সারিতে i টি অঙ্ক। বিজোড় সারি 1 দিয়ে আর জোড় সারি 0 দিয়ে শুরু হয়, তারপর 1 ও 0 পালাক্রমে আসে। দুটি নিয়মকে একসাথে লেখা যায়: (i + j) জোড় হলে 1, বিজোড় হলে 0 (i ও j 1 থেকে গোনা)।
/* C */
#include <stdio.h>
int main(void) {
int n;
printf("Enter n: ");
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++)
printf("%d", (i + j) % 2 == 0 ? 1 : 0);
printf("\n");
}
return 0;
}
// Java
import java.util.Scanner;
public class BinaryFloyd {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for (int i = 1; i <= n; i++) {
StringBuilder row = new StringBuilder();
for (int j = 1; j <= i; j++)
row.append((i + j) % 2 == 0 ? 1 : 0);
System.out.println(row);
}
}
}
যাচাই: i = 1: j = 1 → 2 জোড় → "1"। i = 2: 3 → 0, 4 → 1 → "01"। i = 4: 5, 6, 7, 8 → "0101"। প্রশ্নের নমুনার সঙ্গে হুবহু মেলে ✔। প্রচলিত সংখ্যাভিত্তিক Floyd's triangle (1 / 2 3 / 4 5 6 …) চাইলে একটি counter রেখে প্রতিবার printf("%d ", c++) লিখুন।
#include <stdio.h>
int fun(int i) {
if (i <= 0) return;
printf("%d, ", i--);
fun(--i);
printf("%d, ", i);
}
int main() {
fun(5);
}মনে রাখুন: i-- (post-decrement) আগে মান ব্যবহার করে, তারপর কমায়। --i (pre-decrement) আগে কমায়, তারপর মান ব্যবহার করে। তাই প্রতিটি call-এ i মোট ২ কমে। দ্বিতীয় printf recursive call ফেরার পরে চলে, তাই ওই মানগুলো উল্টো ক্রমে ছাপা হয়।
| Call | প্রথম printf | i-এর পরিবর্তন | Recursive call | ফেরার পর দ্বিতীয় printf |
|---|---|---|---|---|
| fun(5) | "5, " | i-- → 4, --i → 3 | fun(3) | "3, " (সবশেষে) |
| fun(3) | "3, " | i-- → 2, --i → 1 | fun(1) | "1, " |
| fun(1) | "1, " | i-- → 0, --i → −1 | fun(−1) | "−1, " |
| fun(−1) | — | i ≤ 0, তাই কিছু না ছেপেই return | ||
ক্রম: নামার পথে 5, 3, 1 → fun(−1) ফেরে → ওঠার পথে −1 (fun(1)), 1 (fun(3)), 3 (fun(5))।
int fun() একটি non-void function, অথচ return;-এ কোনো মান নেই এবং শেষেও return নেই। C99/C11-এ এটি constraint violation বা warning, কিন্তু যেহেতু ফেরত মানটি কোথাও ব্যবহার হয়নি, বেশিরভাগ compiler (gcc) warning দিয়ে উপরের output-ই দেয়। প্রশ্নপত্রের "I", "Printf" ও "Ø" OCR বা টাইপের ভুল; সেগুলো i, printf ও 0 ধরা হয়েছে।
CREATE TABLE Department (DeptCode INT, DeptName VARCHAR(20), Location VARCHAR(20));
CREATE TABLE Employee (EmpCode INT, EmpFname VARCHAR(20), Salary INT,
Commission INT, DeptCode VARCHAR(20));
(a) Select every EmpFname with total salary (total salary = salary + commission). (b) Select EmpFname and Location of employees whose salary is greater than the average salary, ordered by EmpFname. (c) Select EmpFname and the count of employees, ordered by the employee count ascending.Schema সংশোধন (উত্তরে উল্লেখ করুন): Employee-র DeptCode-এর type Department-এর DeptCode-এর মতোই INT হওয়া উচিত, যাতে join ও foreign key ঠিকমতো কাজ করে। মূল DDL-এ Commission INT-এর পরে কমা নেই এবং শেষে একটি বাড়তি কমা আছে; দুটোই syntax error।
CREATE TABLE Department (
DeptCode INT PRIMARY KEY,
DeptName VARCHAR(20),
Location VARCHAR(20)
);
CREATE TABLE Employee (
EmpCode INT PRIMARY KEY,
EmpFname VARCHAR(20),
Salary INT,
Commission INT,
DeptCode INT REFERENCES Department(DeptCode)
);
-- (a) Total salary; Commission NULL হলে 0 ধরা হয়
SELECT EmpFname,
Salary + COALESCE(Commission, 0) AS TotalSalary
FROM Employee;
-- (b) গড় বেতনের চেয়ে বেশি পান যাঁরা, তাঁদের নাম ও Location
SELECT e.EmpFname, d.Location
FROM Employee e
JOIN Department d ON e.DeptCode = d.DeptCode
WHERE e.Salary > (SELECT AVG(Salary) FROM Employee)
ORDER BY e.EmpFname;
-- (c) প্রতিটি EmpFname-এ কতজন কর্মচারী, সংখ্যার ক্রমে
SELECT EmpFname, COUNT(EmpCode) AS EmpCount
FROM Employee
GROUP BY EmpFname
ORDER BY EmpCount ASC;
NULL + সংখ্যা = NULL, তাই COALESCE (বা MySQL-এ IFNULL, SQL Server-এ ISNULL) না দিলে কমিশনহীন কর্মচারীর total salary NULL দেখাবে।(b): WHERE-এ সরাসরি
AVG() ব্যবহার করা যায় না, তাই subquery লাগে।(c): প্রশ্নটি অস্পষ্ট। Aggregate-এর সঙ্গে non-aggregate কলাম (EmpFname) রাখতে হলে সেটি GROUP BY-তে থাকতে হবে। উপরে "একই নামে কতজন" ধরা হয়েছে। যদি উদ্দেশ্য হয় প্রতিটি বিভাগে কতজন কর্মচারী, তাহলে:
SELECT d.DeptName, COUNT(e.EmpCode) AS EmpCount
FROM Department d LEFT JOIN Employee e ON e.DeptCode = d.DeptCode
GROUP BY d.DeptName
ORDER BY EmpCount ASC;
আর প্রতিটি নামের পাশে মোট কর্মচারী সংখ্যা দেখাতে চাইলে window function: SELECT EmpFname, COUNT(*) OVER () AS TotalEmp FROM Employee ORDER BY EmpCode;। খাতায় নিজের ব্যাখ্যাটি এক লাইনে লিখে দিন।
| বিষয় | Stack | Queue |
|---|---|---|
| নীতি | LIFO (Last In First Out) | FIFO (First In First Out) |
| প্রান্ত | একটি প্রান্ত (top)। এখানেই insert ও delete হয় | দুটি প্রান্ত: rear-এ insert, front-এ delete |
| অপারেশন | push, pop, peek | enqueue, dequeue, front |
| Pointer | top | front ও rear |
| Complexity | push/pop O(1) | enqueue/dequeue O(1) (circular array বা linked list-এ) |
| রূপভেদ | — | Circular queue, priority queue, deque |
| বাস্তব উদাহরণ | প্লেটের স্তূপ | ব্যাংকের কাউন্টারের লাইন |
- Function call ও recursion-এর call stack, যেখানে return address ও local variable থাকে।
- Expression evaluation ও infix → postfix রূপান্তর; balanced parentheses যাচাই।
- (অতিরিক্ত) Undo/Redo, ব্রাউজারের Back বাটন, DFS।
- CPU scheduling (Round Robin ready queue) ও printer spooling।
- BFS traversal; নেটওয়ার্ক router-এর packet buffer।
- (অতিরিক্ত) ব্যাংকের টোকেন সিস্টেম, message queue (RabbitMQ, Kafka)।
সংজ্ঞা: Polymorphism (poly = অনেক, morph = রূপ) মানে একই interface বা নাম দিয়ে ভিন্ন ভিন্ন type-এর object-এর সঙ্গে ভিন্ন আচরণ করা। এটি OOP-এর চারটি স্তম্ভের একটি; বাকি তিনটি encapsulation, inheritance ও abstraction।
| ধরন | অন্য নাম | কীভাবে | Binding |
|---|---|---|---|
| Compile-time | Static polymorphism | Method overloading (একই নাম, ভিন্ন parameter); C++-এ operator overloading | Early/static binding |
| Runtime | Dynamic polymorphism | Method overriding + upcasting (parent reference, child object); C++-এ virtual function | Late/dynamic binding |
| Parametric | Generics / Templates | Java-র List<T>, C++ template। একই কোড বিভিন্ন type-এর সঙ্গে কাজ করে | Compile time |
// Compile-time: overloading
class Calculator {
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
int add(int a, int b, int c) { return a + b + c; }
}
// Runtime: overriding
abstract class Account {
abstract double interest(double balance);
}
class Savings extends Account {
@Override double interest(double b) { return b * 0.05; }
}
class FixedDeposit extends Account {
@Override double interest(double b) { return b * 0.09; }
}
public class Bank {
public static void main(String[] args) {
Calculator c = new Calculator();
System.out.println(c.add(2, 3)); // 5 (int version)
System.out.println(c.add(2.5, 3.5)); // 6.0 (double version)
Account[] list = { new Savings(), new FixedDeposit() };
for (Account a : list) // একই call, ভিন্ন আচরণ
System.out.println(a.interest(10000)); // 500.0, 900.0
}
}
সুবিধা: নতুন account type যোগ করলে Bank-এর লুপ বদলাতে হয় না (Open–Closed principle)। কোড পুনর্ব্যবহারযোগ্য ও extensible হয়।
ER model-এ relationship মানে দুই বা ততোধিক entity-র মধ্যে সম্পর্ক। একে তিনভাবে শ্রেণিবিভাগ করা হয়।
(ক) Cardinality (mapping) অনুযায়ী
| ধরন | অর্থ | উদাহরণ | টেবিলে বাস্তবায়ন |
|---|---|---|---|
| One-to-One (1:1) | A-এর একটি record, B-এর সর্বোচ্চ একটির সঙ্গে | Customer — NID; Employee — Desk | যেকোনো এক পাশে UNIQUE foreign key |
| One-to-Many (1:N) | A-এর একটি, B-এর অনেকের সঙ্গে | Branch — Accounts; Department — Employees | "Many" পাশের টেবিলে foreign key |
| Many-to-One (N:1) | 1:N-এর উল্টো দিক থেকে দেখা | Accounts — Branch | একই |
| Many-to-Many (M:N) | দুই পাশেই অনেক | Customer — Account (joint account); Student — Course | Junction (bridge) টেবিল, দুই FK মিলিয়ে composite PK, যেমন প্রশ্ন ২-এর R ও Q |
(খ) Degree অনুযায়ী
- Unary (recursive): একই entity নিজের সঙ্গে সম্পর্কিত, যেমন Employee manages Employee, বা Node next Node (token ring)।
- Binary: দুটি entity, যেমন Customer holds Account। এটিই সবচেয়ে প্রচলিত।
- Ternary: তিনটি entity একসাথে, যেমন Doctor–Patient–Medicine (prescribes), বা Supplier–Part–Project।
(গ) Participation অনুযায়ী
- Total (mandatory): প্রতিটি record-কে সম্পর্কে থাকতেই হবে, যেমন প্রতিটি Loan-এর একজন Borrower থাকবেই। ER diagram-এ এটি দুই দাগ দিয়ে দেখানো হয়।
- Partial (optional): সব record-এর থাকা জরুরি নয়, যেমন সব Customer-এর Loan নেই।
"Relation" শব্দটি দিয়ে যদি টেবিল বোঝানো হয়: base relation (সংরক্ষিত টেবিল), view (virtual relation) ও query result (derived relation)। প্রয়োজনে উত্তরের শেষে এক লাইনে যোগ করুন।
মডেল উত্তর (নিজের প্রজেক্ট অনুযায়ী বদলে নিন):
১. প্রজেক্ট পরিচিতি: "Micro-Loan Management System" — একটি ওয়েব অ্যাপ্লিকেশন, যা একটি NGO বা ক্ষুদ্রঋণ প্রতিষ্ঠানের ঋণ আবেদন, অনুমোদন, কিস্তি সংগ্রহ ও রিপোর্ট পরিচালনা করে। ব্যবহারকারী প্রায় ৫০ জন মাঠকর্মী ও ১০ জন শাখা ব্যবস্থাপক; গ্রাহকের রেকর্ড প্রায় ২০,০০০।
২. প্রযুক্তি ও আমার ভূমিকা: Java (Spring Boot) REST API, MySQL, React frontend, Git ও Docker। আমি backend ডেভেলপার হিসেবে database design, কিস্তি হিসাবের মডিউল ও রিপোর্টিং তৈরি করেছি। কাজ চলেছে Agile (২ সপ্তাহের sprint) পদ্ধতিতে।
| চ্যালেঞ্জ | কারণ | সমাধান |
|---|---|---|
| একই কিস্তি দুবার পোস্ট হওয়া (double posting) | দুর্বল নেটওয়ার্কে মাঠকর্মী বারবার Submit চাপতেন; concurrent request | Transaction (@Transactional) ও row-level lock ব্যবহার; প্রতিটি পেমেন্টে idempotency key; ক্লিকের পর বাটন নিষ্ক্রিয় |
| মাসিক রিপোর্ট খুব ধীর (প্রায় ৪০ সেকেন্ড) | বড় টেবিলে full table scan; N+1 query | EXPLAIN দিয়ে বিশ্লেষণ; (branch_id, due_date)-এ composite index; JOIN FETCH; রাতের batch-এ summary টেবিল। ফলে সময় নেমে আসে ২ সেকেন্ডের নিচে |
| Requirement বারবার বদলানো | সুদের হার ও জরিমানার নিয়ম শাখাভেদে ভিন্ন | নিয়মগুলো কোডে hard-code না করে configuration টেবিলে রাখা; প্রতিটি sprint শেষে demo দিয়ে feedback নেওয়া |
| নিরাপত্তা | সংবেদনশীল আর্থিক ও ব্যক্তিগত তথ্য | bcrypt দিয়ে password hashing; role-based access (RBAC); prepared statement দিয়ে SQL injection প্রতিরোধ; HTTPS; audit log |
| Deployment-এ "আমার পিসিতে চলে, সার্ভারে চলে না" | পরিবেশের পার্থক্য | Docker image, CI pipeline (GitHub Actions) এবং স্বয়ংক্রিয় unit ও integration test |
৩. ফলাফল ও শিক্ষা: কাগজের খাতার বদলে রিয়েল-টাইম ড্যাশবোর্ড চালু হয় এবং হিসাবের ভুল প্রায় শূন্যে নেমে আসে। শিক্ষা: শুরুতেই ডেটার অখণ্ডতা (transaction, constraint) নিশ্চিত করা, performance মেপে তারপর অপ্টিমাইজ করা, আর ব্যবহারকারীর সঙ্গে নিয়মিত যোগাযোগ রাখা জরুরি। ব্যাংকের Assistant Programmer হিসেবে CBS-সংলগ্ন অ্যাপ বা ইন্টারনাল টুল তৈরিতে এই অভিজ্ঞতা সরাসরি কাজে লাগবে।