Module ৪ · if, switch আর loop
প্রতিটা statement, একটা একটা করে
এই lesson-এ যা শিখবে
ifথেকে label দেওয়াbreakপর্যন্ত control flow-এর প্রতিটা statement লিখতে পারবে, আর বলতে পারবে কোনটার test আর body কতবার চলে।breakছাড়া একটাswitchcase কেন পরের case-এ গড়িয়ে পড়ে, বুঝিয়ে বলতে পারবে, আর যে case-গুলো একই body ভাগ করে, সেখানে এটা ইচ্ছে করে কাজে লাগাতে পারবে।breakদিয়ে loop আগেভাগে থামাতে পারবে,continueদিয়ে একটা pass-এর বাকিটা বাদ দিতে পারবে, আর label দিয়ে একসাথে দুইটা loop থেকে বের হতে পারবে।
Bob একটা switch লিখেছে, যেটা দিনের নম্বর থেকে দিনের নাম বের করে। Day 6-এর জন্য ও আশা করে একটাই লাইন, Saturday। অথচ program print করে তিনটা: Saturday, Sunday আর not a day। কোনো error আসে না, কারণ Bob যা লিখেছে JavaScript হুবহু তাই করেছে। কেন এমন হলো, আর এক শব্দের সমাধানটা কী, সেটা দেখাবে switch-এর অংশটা।
Control flow মানে statement-গুলো কোন ক্রমে চলে। Lesson 01 পুরো ছবিটা এঁকেছে: if, else, for loop আর for...of। এই lesson প্রতিটা statement-এর কাছে একবার করে যাবে: তার syntax, ছোট একটা উদাহরণ, আসল output আর তার খরচ। খরচ মানে উদাহরণের নিচে এক সারির একটা table: test আর body কতবার চলে।
if আর else
if আর else
if (condition) {
runs when condition is truthy
} else {
runs when condition is falsy
}
conditionযেকোনো expression হতে পারে, সেটাকে truthy বা falsy হিসেবে পড়া হয় (Module 2)।else-এর অংশটা না দিলেও চলে।
const stock = 0;
if (stock > 0) {
console.log("in stock:", stock);
} else {
console.log("sold out");
}
if ("0") {
console.log("the string \"0\" is truthy");
}
sold out
the string "0" is truthy
| কতবার | Test | একটা block |
|---|---|---|
| লাইনটায় যতবার পৌঁছায়, প্রতিবার | একবার | দুইটার ঠিক একটা একবার চলে; else না থাকলে একটা, অথবা একটাও না |
যেটায় চোখ রাখবে: খালি না এমন যেকোনো string truthy, "0"-ও। Falsy-র পুরো তালিকাটা Module 2-এ আছে। তাই if জিজ্ঞেস করে "truthy না falsy?", কখনো "এটা কি সংখ্যা 0?" না।
else if chain: প্রথম true condition-টাই জেতে
else if chain
if (first) {
...
} else if (second) {
...
} else {
runs when no condition was truthy
}
- Condition-গুলো উপর থেকে একটা একটা করে test হয়। প্রথম যেটা truthy, তার block চলে, বাকিগুলো বাদ।
const temp = 31;
if (temp >= 35) {
console.log("very hot");
} else if (temp >= 25) {
console.log("warm");
} else if (temp >= 15) {
console.log("mild");
} else {
console.log("cold");
}
if (temp >= 15) {
console.log("Bob's order says: mild");
} else if (temp >= 25) {
console.log("Bob's order says: warm");
}
warm
Bob's order says: mild
| কতবার | Test-গুলো | একটা block |
|---|---|---|
| k-টা condition | উপর থেকে নিচে, প্রথম truthy-টায় থামে: বড়জোর k বার (এখানে 2) | ঠিক একটা, অথবা শেষে else না থাকলে একটাও না |
যেটায় চোখ রাখবে: ক্রমটা। 31 তো 15-এর চেয়ে বড়, তাই Bob-এর chain প্রথম test-এই থেমে যায়, temp >= 25 পর্যন্ত আর পৌঁছায়ই না। Range নিয়ে কাজ করলে সবচেয়ে বড় সীমাটা আগে test করো, অথবা < দিয়ে সবচেয়ে ছোটটা আগে।
switch: একটা value, অনেকগুলো case
switch
switch (value) {
case A:
runs when value === A
break;
case B:
case C:
shared by B and C
break;
default:
runs when no case matched
}
value-এর হিসাব হয় একবার, তারপর উপর থেকে প্রতিটা case-এর সাথে===দিয়ে মেলানো হয়, তাই কিছুই convert হয় না।breakদিয়েswitchথেকে বের হয়ে যায়। না দিলে run চলতেই থাকে, পরের case-এর লাইনগুলোতে ঢুকে পড়ে।
এই যে Bob-এর program, সত্যি সত্যি চালানো।
const day = 6;
switch (day) {
case 5:
console.log("Friday");
case 6:
console.log("Saturday");
case 7:
console.log("Sunday");
default:
console.log("not a day");
}
Saturday
Sunday
not a day
একটা case শুধু শুরু করার একটা জায়গা। switch খুঁজে বের করে প্রথম কোন case day-এর সমান, সেখানে লাফ দেয়, তারপর তার নিচের প্রতিটা লাইন চালায়। থামে একটা break পেলে, অথবা শেষের brace-এ পৌঁছালে। এর নাম fall-through, মানে নিচে গড়িয়ে পড়া। প্রতিটা case-এর শেষ লাইনে break; বসাও, তাহলে একই program শুধু Saturday print করবে।
Fall-through-এর একটাই সৎ ব্যবহার আছে: কয়েকটা case যখন একই body ভাগ করে। Case-গুলো মাঝে কিছু না রেখে একটার নিচে আরেকটা সাজাও, নিচের মাসগুলোর মতো। আর যে case-এ লাইন আছে অথচ ইচ্ছে করেই নিচে গড়ায়, তার গায়ে একটা // falls through comment দাও। তাহলে পরের পাঠক বুঝবে, এটা Bob-এর মতো bug না।
const month = 4;
let days;
switch (month) {
case 2:
days = 28;
break;
case 4:
case 6:
case 9:
case 11:
days = 30;
break;
default:
days = 31;
}
console.log("month", month, "has", days, "days");
const plan = "pro";
switch (plan) {
case "pro":
console.log("cloud backup");
// falls through
case "basic":
console.log("email support");
break;
default:
console.log("no extras");
}
month 4 has 30 days
cloud backup
email support
| কতবার | মেলানো | Body-গুলো |
|---|---|---|
| লাইনটায় যতবার পৌঁছায়, প্রতিবার | value একবার, তারপর উপর থেকে case ধরে ধরে, যতক্ষণ না একটা === হয় (day 6: দুইবার মেলানো) | মিলে যাওয়া case থেকে নিচে প্রথম break পর্যন্ত |
যেটায় চোখ রাখবে: === মানে string "6" কখনো case 6-এর সাথে মেলে না, তাই চলে default ("যে ভুলগুলো সবাই করে"-র 3 নম্বর)। মাসের code-টা leap year ধরে না, আর default-এ পৌঁছায় তখনই, যখন সব case ফেল করে।
while: আগে test, তারপর body
while
while (condition) {
body
}
- প্রতিটা pass-এর আগে test চলে। প্রথমবারেই falsy হলে body একবারও চলে না।
let height = 16;
let bounces = 0;
while (height >= 1) {
console.log("bounce to", height);
height = height / 2;
bounces++;
}
console.log("bounces:", bounces, "height now:", height);
bounce to 16
bounce to 8
bounce to 4
bounce to 2
bounce to 1
bounces: 5 height now: 0.5
| কতবার | Test | Body |
|---|---|---|
| n-টা pass | n + 1 বার (এখানে 6: শেষবার উত্তর false) | n বার, 0-ও হতে পারে (এখানে 5) |
কয়টা pass লাগবে আগে থেকে জানা না থাকলে while loop মানায়: কখন থামতে হবে জানো, কয়বার ঘুরবে জানো না। যেটায় চোখ রাখবে: body-কে condition-টা false-এর দিকে ঠেলতে হবে। height = height / 2; মুছে দাও, loop আর কোনোদিন শেষ হবে না। Playground-এ এমন run time limit-এ গিয়ে থামে, মোটামুটি 10 সেকেন্ডে, "Time Limit Exceeded" দেখিয়ে।
do...while: body অন্তত একবার চলে
do...while
do {
body
} while (condition);
- আগে body চলে, তারপর test ঠিক করে আবার ঘুরবে কি না। শেষের parenthesis-এর পরের semicolon-টা খেয়াল করো।
let n = 10;
while (n < 5) {
console.log("while body, n =", n);
n++;
}
do {
console.log("do body, n =", n);
n++;
} while (n < 5);
console.log("after both loops, n =", n);
do body, n = 10
after both loops, n = 11
Condition n < 5 শুরু থেকেই false। While loop আগে জিজ্ঞেস করে, তাই তার body একবারও চলে না। do...while loop আগে body চালায়, তারপর জিজ্ঞেস করে। ধাপে ধাপে দেখো।
দুইটা loop নিচে flowchart হিসেবে আঁকা। তফাত একটাই: test-টা কোথায় বসে।
| কতবার | Test | Body |
|---|---|---|
| n-টা pass, n অন্তত 1 | n বার, প্রতিটা pass-এর পরে একবার (এখানে 1) | n বার, কখনো 0 না (এখানে 1) |
যেটায় চোখ রাখবে: do...while তখনই নাও, যখন প্রশ্নটার মানে দাঁড়ানোর আগেই body-কে একবার চলতে হবে। প্রথম choice-এর আগে একবার menu দেখানো, বা 0-এর digit গোনা, এগুলোই চেনা উদাহরণ (Example 2)।
for: start, test, step
for
for (start; test; step) {
body
}
for (;;) { ... } all three parts empty: runs until a break
startচলে একবার,testপ্রতিটা pass-এর আগে,stepপ্রতিটা pass-এর পরে (lesson 01)।- তিনটা অংশের যেকোনোটা খালি রাখা যায়। খালি test-কে true ধরা হয়।
for (let i = 3; i >= 1; i--) {
console.log("countdown", i);
}
let k = 0;
for (; k < 5; ) {
k += 2;
}
console.log("k is", k);
countdown 3
countdown 2
countdown 1
k is 6
দ্বিতীয় loop-এ start নেই, step-ও নেই: k বানানো হয়েছে আগেই, আর body সেটা বদলায়। এটা আসলে for loop-এর জামা পরা একটা while loop, তাই সোজা লেখো while (k < 5)। for (;;) হলো এমন loop, যার কোনো test-ই নেই। এটা টাইপের ভুল না: ভিতরের একটা break না আসা পর্যন্ত চলতে থাকে, break-এর অংশে যেমন দেখবে।
| কতবার | start, test, step | Body |
|---|---|---|
| n-টা pass | start একবার, test n + 1 বার, step n বার (countdown: 1, 4, 3) | n বার (countdown: 3) |
যেটায় চোখ রাখবে: counter হবে let। const counter প্রথম step-এই throw করে TypeError: Assignment to constant variable. (lesson 01)।
for...of: array বা string-এর প্রতিটা value
for...of
for (const item of list) {
body, with item holding the next value
}
listহলো এমন কিছু, যার value-গুলো ক্রম ধরে সাজানো: একটা array (Module 7) বা একটা string (Module 3)।- প্রতিটা pass নতুন একটা
itemপায়, তাই এখানেconstচলে, সাধারণ for loop-এর counter-এর মতো না।
const prices = [120, 45, 300];
let total = 0;
for (const price of prices) {
total += price;
}
console.log("total:", total);
for (const ch of "hi!") {
console.log(ch);
}
total: 465
h
i
!
| কতবার | Test | Body |
|---|---|---|
| n-টা value | লিখতে হয় না; loop নিজে n + 1 বার পরের value চায় | n বার (এখানে 3, তারপর আবার 3) |
যেটায় চোখ রাখবে: for...of দেয় value, position না। Position-ও লাগলে i দিয়ে সাধারণ for loop লেখো। সাধারণ object-এর দেওয়ার মতো ক্রম ধরা value নেই, তাই for...of সেটা নিতে রাজি হয় না ("যে ভুলগুলো সবাই করে"-র 4 নম্বর)।
for...in: object-এর key, আর array-র ফাঁদ
for...in
for (const key in object) {
body, with key holding the next key, always a string
}
- Key হলো object-এর একটা অংশের নাম। Object শেখাবে Module 8; এখানে শুধু এক ঝলক।
const stock = { pens: 12, books: 0, bags: 5 };
for (const item in stock) {
console.log(item, stock[item]);
}
const marks = [90, 75];
for (const i in marks) {
console.log(i, typeof i, i + 1);
}
pens 12
books 0
bags 5
0 string 01
1 string 11
stock[item] সেই অংশটা পড়ে, যার নাম আছে item-এ। ফাঁদটা দ্বিতীয় loop-এ। Array-র উপর for...in position-গুলো দেয় string হিসেবে, "0" আর "1"। তাই i + 1 text জোড়ে আর দেয় "01", Module 2-এর সেই +-এর নিয়ম।
| কতবার | Test | Body |
|---|---|---|
| k-টা key | লিখতে হয় না | k বার, প্রতিটা key-র জন্য একবার (এখানে 3, তারপর 2) |
যেটায় চোখ রাখবে: for...in বানানো হয়েছে object-এর key-র জন্য। Array-র উপর value চাইলে for...of, position চাইলে সাধারণ for loop।
break: এখনই loop থেকে বের হও
break
break; leaves the innermost loop or switch around it
const queue = [4, 9, -1, 7];
for (const ticket of queue) {
if (ticket < 0) {
console.log("bad ticket, stop");
break;
}
console.log("serve", ticket);
}
let rounds = 0;
for (;;) {
rounds++;
if (rounds === 3) {
break;
}
}
console.log("rounds:", rounds);
serve 4
serve 9
bad ticket, stop
rounds: 3
Ticket 7 কখনো পড়াই হয় না: loop -1-এই শেষ। for (;;) loop-এর কোনো test নেই, তাই ওর break-ই বের হওয়ার একমাত্র দরজা।
| কতবার | Test | Body |
|---|---|---|
| p নম্বর pass-এ break | তারপর আর কোনো test হয় না | p-টা pass, শেষটা মাঝপথে কাটা (ticket: 4-টার মধ্যে 3) |
যেটায় চোখ রাখবে: break-কে থাকতে হবে একটা loop বা switch-এর ভিতরে। অন্য কোথাও থাকলে program শুরুই হয় না ("যে ভুলগুলো সবাই করে"-র 1 নম্বর)।
continue: পরের pass-এ চলে যাও
continue
continue; skips the rest of this pass; the loop goes on
for (let seat = 1; seat <= 6; seat++) {
if (seat % 3 === 0) {
continue;
}
console.log("seat", seat);
}
seat 1
seat 2
seat 4
seat 5
Seat 3 আর 6 বাদ পড়েছে। For loop-এ continue লাফ দেয় step-এ, তাই seat++ তবুও চলে, আর loop এগিয়ে যায়।
| কতবার | Test | Body |
|---|---|---|
| n-টা pass | আগের মতোই n + 1 বার (এখানে 7) | শুরু হয় n বার, শেষ হয় শুধু যেখানে continue চলেনি (এখানে 6 আর 4) |
যেটায় চোখ রাখবে: while loop-এ আলাদা কোনো step অংশ নেই। Counter বদলানোর লাইনের আগে continue বসালে সেই লাইনটাও বাদ পড়ে, আর loop কখনো শেষ হয় না।
Label দেওয়া break আর continue Intermediate
Label
name: for (...) {
for (...) {
break name; leaves the loop called name
continue name; goes to the next pass of the loop called name
}
}
- Label হলো একটা loop-এর ঠিক আগে লেখা একটা নাম আর একটা colon। এটা ব্যবহার করে শুধু
breakআরcontinue।
outer: for (let row = 1; row <= 9; row++) {
for (let col = 1; col <= 9; col++) {
if (row * col > 20) {
console.log("first product above 20:", row, "x", col);
break outer;
}
}
}
rows: for (let row = 1; row <= 3; row++) {
for (let col = 1; col <= 3; col++) {
if (col > row) {
continue rows;
}
console.log(row, col);
}
}
first product above 20: 3 x 7
1 1
2 1
2 2
3 1
3 2
3 3
সাধারণ একটা break শুধু ভিতরের loop থেকে বের হতো, আর বাইরেরটা row 4 শুরু করে দিত। break outer একসাথে দুইটা থেকেই বের করে আনে। continue rows একটা row-এর বাকিটা ফেলে রেখে পরের row শুরু করে, আর তাতেই একটা ত্রিভুজ print হয়।
| কতবার | Test-গুলো | ভিতরের body |
|---|---|---|
| 9 বাই 9 grid, 3 x 7-এ break outer | break-এর পরে কোনো loop-এর আর test হয় না | 9 + 9 + 7 = 25 বার, 81 বার না |
যেটায় চোখ রাখবে: label একটা loop-এর নাম, আর দুই মাথায় বানান হুবহু এক হতে হবে ("যে ভুলগুলো সবাই করে"-র 2 নম্বর)। return সহ ছোট একটা function (Module 5) প্রায়ই একই কাজ করে দেয়; loop-গুলো অনেক variable ভাগ করলে label-টাই মানায়।
Alice দিনে 20 পাতা পড়ে। 130 পাতার একটা বই শেষ করতে কয় দিন লাগবে, আর শেষ দিনে কয় পাতা বাকি থাকবে?
const pages = 130;
const perDay = 20;
let read = 0;
let days = 0;
while (read < pages) {
read += perDay;
days++;
}
console.log("days:", days);
console.log("pages on the last day:", pages - (read - perDay));
days: 7
pages on the last day: 10
Loop শুরুর আগে কয়বার ঘুরবে জানা নেই, তাই while loop মানায়। ছয় দিনে ও পড়ে ফেলে 120 পাতা, আর সপ্তম দিনে শেষ 10 পাতা।
Run in Compilerdo...while দিয়ে digit গোনাএকটা সংখ্যার digit গুনতে শেষের digit-টা কেটে ফেলতে থাকো, যতক্ষণ না কিছুই বাকি থাকে। 0-এরও একটা digit আছে, আর ঠিক এই কারণেই এই loop test করে শেষে।
const numbers = [0, 7, 42, 90210];
for (const number of numbers) {
let n = number;
let digits = 0;
do {
digits++;
n = Math.floor(n / 10);
} while (n > 0);
console.log(number, "has", digits, "digit(s)");
}
0 has 1 digit(s)
7 has 1 digit(s)
42 has 2 digit(s)
90210 has 5 digit(s)
Math.floor(n / 10) শেষের digit-টা ফেলে দেয়, Module 1-এর সেই নিচের দিকে round করা। While loop হলে 0 > 0 test সাথে সাথেই ফেল করত, আর 0 পেত 0-টা digit।
Amara-র bus card শুরু হয় কিছু balance দিয়ে। প্রতিটা ride-এর একটা ভাড়া আছে। যে ride-এর ভাড়া balance-এ কুলায় না, সেটা বাতিল, card পরের ride-এর জন্য অপেক্ষা করে। Balance ঠিক 0 হয়ে গেলে সেদিনের মতো card আর কাজ করে না।
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
let balance = nextInt();
const rides = nextInt();
let paid = 0;
for (let ride = 1; ride <= rides; ride++) {
const fare = nextInt();
if (fare > balance) {
out.push("ride " + ride + ": refused, balance " + balance);
continue;
}
balance -= fare;
paid++;
out.push("ride " + ride + ": paid " + fare + ", balance " + balance);
if (balance === 0) {
out.push("card empty after ride " + ride);
break;
}
}
out.push("rides paid: " + paid);
console.log(out.join("\n"));
ride 1: paid 30, balance 70
ride 2: paid 50, balance 20
ride 3: refused, balance 20
ride 4: paid 20, balance 0
card empty after ride 4
rides paid: 3
ওই output-টা input-এর প্রথম লাইনে 100 5 আর পরের লাইনে 30 50 40 20 10 থাকলে। Ride 3-এর ভাড়া 40, অথচ বাকি আছে 20, তাই continue টাকা কাটার লাইনগুলো বাদ দিয়ে যায়। Ride 4 card খালি করে দেয়, তাই break loop শেষ করে, আর ride 5 পড়াই হয় না।
এটা কোথায় কাজে লাগে
- Redux। Redux documentation reducer লেখে একটা
switch (action.type)দিয়ে: প্রতিটা action-এর জন্য একটাcase, আর একটাdefault, যেটা state না বদলে ফেরত দেয়। - ESLint। এর
no-fallthroughrule recommended set-এ চালু থাকে, আর কোনো case পরেরটায় গড়িয়ে পড়লে ধরিয়ে দেয়। "falls through" লেখা একটা comment থাকলে rule বুঝে নেয়, গড়ানোটা ইচ্ছে করে। - TypeScript।
noFallthroughCasesInSwitchcompiler option চালু করলে, code আছে এমন case পরেরটায় গড়িয়ে পড়লে সেটা error হয়ে যায়। উপরের মাসগুলোর মতো খালি, সাজানো case-গুলো তবুও চলে। - Node-এর REPL। শুধু
nodeটাইপ করলে খোলে একটা read, evaluate, print loop: একটা লাইন পড়ে, চালায়, ফল print করে, আর এভাবে চলতে থাকে যতক্ষণ না তুমি.exitলেখো। এটা এমন একটা loop, যেটা একটা sentinel না আসা পর্যন্ত চলে: sentinel মানে থামার একটা value, যেটা data-র অংশ না।
যে ভুলগুলো সবাই করে
১. Loop-এর বাইরে break।
const stock = 0;
if (stock === 0) {
console.log("sold out");
break;
}
কোনো লাইন চলার আগেই program থেমে যায়: SyntaxError: Illegal break statement। if তো loop না, তাই break-এর বের হওয়ার মতো কিছু নেই। ওটা মুছে দাও, অথবা বাকি কাজটা একটা else-এ রাখো। তুমি এটা লিখবে, কারণ break শুনলে মনে হয় "এখানেই থামো"।
২. এমন label-এ continue, যেটা আসলে নেই।
rows: for (let r = 1; r <= 2; r++) {
for (let c = 1; c <= 2; c++) {
if (c === 2) {
continue row;
}
console.log(r, c);
}
}
কোনো লাইন চলার আগেই program থেমে যায়: SyntaxError: Undefined label 'row'। Label-টা rows, অথচ continue row এমন একটা loop-এর নাম বলছে, যেটা নেই। দুই মাথায় বানান এক রাখো। ভুলটা হবে, কারণ নাম দুইটায় তফাত মাত্র একটা অক্ষর।
৩. Number-এর case-এর সাথে token-এর string।
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
const choice = next();
switch (choice) {
case 1:
out.push("new game");
break;
case 2:
out.push("quit");
break;
default:
out.push("unknown option");
}
console.log(out.join("\n"));
unknown option
Input 1-এর জন্য কোনো error নেই, অথচ ভুল branch চলে। next() দেয় string "1", আর "1" === 1 হলো false। nextInt() দিয়ে পড়ো, অথবা লেখো case "1":। ভুলটা হবে, কারণ == হলে মিলে যেত, আর switch কখনো == ব্যবহার করে না।
৪. সাধারণ object-এর উপর for...of।
const week = { mon: 7500, tue: 8000 };
for (const steps of week) {
console.log(steps);
}
TypeError: week is not iterable
Iterable মানে "নিজের value-গুলো একটা একটা করে দিতে পারে", যেমন array আর string পারে। সাধারণ object পারে না, তাই প্রথম pass-এর আগেই loop throw করে। লেখো for (const day in week), আর পড়ো week[day]। ভুলটা হবে, কারণ for...of আর for...in-এ তফাত মাত্র দুইটা অক্ষরের।
David 100 নম্বরের একটা class test-এর খাতা দেখে, আর প্রতিটা নম্বরকে একটা letter-এ বদলায়। কিছু নম্বর ভুল করে টাইপ হয়েছে, তাই 0 থেকে 100-এর বাইরের নম্বরের জন্য বলতে হবে invalid।
Input. n, তারপর n-টা পূর্ণসংখ্যা নম্বর।
Output. প্রতিটা নম্বরের জন্য এক লাইন। 90 থেকে 100 হলে A, 80 থেকে 89 হলে B, 70 থেকে 79 হলে C। 60 থেকে 69 হলে D, আর 0 থেকে 59 হলে F। 0-এর কম বা 100-এর বেশি নম্বর হলে invalid।
Constraints. 1 <= n <= 100000; -1000 <= mark <= 1000।
Sample. Input 7, তারপর 95 89 70 65 59 101 -1 দিলে সাত লাইনে A, B, C, D, F, invalid আর invalid।
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
// your code: read with next() and nextInt(), push every line of output to out
console.log(out.join("\n"));
letter-grade নামে grade হয়। Hidden test-গুলো সীমার প্রতিটা নম্বর দিয়ে চালায়, যেমন 89 আর 90, 0 আর 100, আর range-এর ঠিক বাইরের নম্বর।
Bob চায়, এবার ওর দিনের নামের switch-টা ঠিকঠাক চলুক। দিনগুলোর নম্বর 1 (Monday) থেকে 7 (Sunday), আর weekend-এর দুই দিন যেন একটাই body ভাগ করে।
Input. n, তারপর n-টা পূর্ণসংখ্যা।
Output. প্রতিটা সংখ্যার জন্য এক লাইন: দিনের ইংরেজি নাম, একটা space, তারপর weekday (1 থেকে 5) অথবা weekend (6 আর 7); অন্য যেকোনো সংখ্যার জন্য invalid। নামগুলো Monday, Tuesday, Wednesday, Thursday, Friday, Saturday আর Sunday।
Constraints. 1 <= n <= 100000; -1000 <= প্রতিটা সংখ্যা <= 1000।
Sample. Input 4, তারপর 1 6 7 9 দিলে চার লাইনে Monday weekday, Saturday weekend, Sunday weekend আর invalid।
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
// your code: read with next() and nextInt(), push every line of output to out
console.log(out.join("\n"));
day-name নামে grade হয়। Hidden test-গুলো 1 থেকে 7-এর প্রতিটা দিন দিয়ে চালায়, সাথে 0, 8 আর negative সংখ্যা দিয়েও।
Zara ওর দোকানে যত টাকা আসে আর যায়, সব সংখ্যা হিসেবে লিখে রাখে, আর দিন শেষ হলে লেখে 0। ও জানতে চায়, কয়টা entry লিখেছে আর সব মিলিয়ে যোগফল কত।
Input. Space বা line break দিয়ে আলাদা করা পূর্ণসংখ্যা। তালিকা শেষ হয় প্রথম 0-তে, আর সেই 0 তালিকার অংশ না; ওই 0-এর পরে যা আছে, সব বাদ। অন্তত একটা 0 সবসময় থাকে।
Output. দুই লাইন: প্রথম 0-এর আগে কয়টা সংখ্যা এসেছে, আর তাদের যোগফল।
Constraints. প্রথম 0-এর আগে বড়জোর 100000-টা সংখ্যা; প্রতিটা -1000000 থেকে 1000000-এর মধ্যে।
Sample. Input 5 -2 7 0 4 4 দিলে দুই লাইনে 3 আর 10।
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
// your code: read with next() and nextInt(), push every line of output to out
console.log(out.join("\n"));
sum-until-zero নামে grade হয়। Hidden test-গুলো একদম প্রথম সংখ্যাটাই 0, negative সংখ্যা, আর 0-এর পরের সংখ্যা দিয়ে চালায়।
Alice একটা bus ride-এর জন্য playlist বানায়, ride-টা নির্দিষ্ট লম্বা। ও গানগুলো ক্রম ধরে বাজায়, তবে 300 সেকেন্ডের চেয়ে লম্বা গান বাদ দেয়। পরের গানটা বাজালে মোট সময় ride-এর দৈর্ঘ্য পেরিয়ে যাবে, এমন হলে ও থেমে যায়, আর কিছুই বাজায় না।
Input. n আর ride-এর দৈর্ঘ্য L সেকেন্ডে, তারপর n-টা গানের দৈর্ঘ্য সেকেন্ডে।
Output. ক্রম ধরে প্রতিটা গান k-এর জন্য এক লাইন। 300-এর চেয়ে লম্বা গান হলে skip k। না হলে, মোট সময় আর এই গান মিলে L-এর বেশি হলে print করো stop at k, তারপর গানের আর কোনো লাইন না। না হলে print করো play k। সবশেষে print করো total, একটা space আর মোট বাজানো সেকেন্ড।
Constraints. 1 <= n <= 1000; 1 <= L <= 100000; 1 <= প্রতিটা দৈর্ঘ্য <= 1000।
Sample. Input 5 600, তারপর 200 400 180 250 90 দিলে আসে play 1, skip 2, play 3, stop at 4 আর total 380। গান 4 বাজালে হতো 630, যেটা 600 পেরিয়ে যায়।
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
// your code: read with next() and nextInt(), push every line of output to out
console.log(out.join("\n"));
আলাদা করে grade হয় না। একটা continue আর একটা break ব্যবহার করো, আর এত ছোট একটা ride দিয়ে চালাও, যাতে প্রথম গানেই থামতে হয়।
Maria k জন বন্ধুর জন্য cinema-র seat book করবে, ওরা এক row-তে পাশাপাশি বসতে চায়। Hall-এ r-টা row, প্রতিটায় c-টা seat, প্রতিটা হয় খালি নয়তো নেওয়া। সামনের row থেকে আর বাঁয়ের seat থেকে খুঁজলে পাশাপাশি k-টা খালি seat-এর প্রথম block কোনটা, সেটা ও জানতে চায়।
Input. r, c আর k, তারপর r-টা লাইন, প্রতিটায় c-টা সংখ্যা: খালি seat হলে 0, নেওয়া হলে 1।
Output. এক লাইন: প্রথম block-এর row আর তার প্রথম seat, দুইটাই 1 থেকে গোনা, মাঝে একটা space। এমন block না থাকলে print করো no seats।
Constraints. 1 <= r, c <= 1000; 1 <= k <= c।
Sample. Input 3 5 3, তারপর row-গুলো 1 0 0 1 0, 0 1 0 0 0 আর 0 0 0 0 0 দিলে আসে 2 3: row 2, seat 3 থেকে 5।
const input = require("fs").readFileSync(0, "utf8");
const tokens = input.split(/\s+/).filter(Boolean);
let at = 0;
const next = () => tokens[at++];
const nextInt = () => Number(next());
const out = [];
// your code: read with next() and nextInt(), push every line of output to out
console.log(out.join("\n"));
আলাদা করে grade হয় না। পুরো hall জমিয়ে না রেখে seat ধরে ধরে পড়ো, আর প্রথম block পেলেই label দেওয়া একটা break দিয়ে দুইটা loop থেকেই বের হয়ে যাও।
সচরাচর যে প্রশ্নগুলো আসে
Switch-এর শেষ case-এও কি break লাগে?
না, শেষের brace এমনিতেই run থামিয়ে দেয়। তবু অনেক team ওটা লিখে রাখে। তাহলে পরে নিচে কেউ নতুন case জুড়লে ভুল করে fall-through ঢুকে পড়ে না।
do...whileআসলে কখন ঠিক loop?যখন test-এর কোনো মানে দাঁড়ানোর আগেই body-কে একবার চলতে হবে। প্রথম choice-এর আগে menu দেখানো, বা এমন সংখ্যার digit কাটা যেটা 0-ও হতে পারে, এগুলোই সাধারণ উদাহরণ। বাকি সব জায়গায় while loop পড়তে বেশি সহজ।
for (;;)কি bug?না, এটা ইচ্ছে করে "চিরকাল চলো" বলা একটা loop। এর ভিতরে একটা
break(বা Module 5-এরreturn) লাগবেই, না হলে সত্যিই চিরকাল চলবে।while (true)-এর মানেও একই, আর অনেকের কাছে সেটা পড়তে সহজ লাগে।Label কি goto-র মতো?
না। JavaScript-এ goto নেই। Label ব্যবহার করতে পারে শুধু
breakআরcontinue, আর শুধু তাদের ঘিরে থাকা একটা loop থেকে বের হতে বা সেটা আবার শুরু করতে। অন্য code-এর মাঝখানে লাফ দেওয়ার কোনো উপায় এতে নেই।
মূল কথা
else ifchain-এ শুধু প্রথম truthy branch-টা চলে, তাই সবচেয়ে কড়া test-টা আগে বসাও।switchমেলায়===দিয়ে, আর মিলে যাওয়া case থেকে নিচে একটাbreakপর্যন্ত চলে; খালি case সাজিয়ে রাখলে তারা একটা body ভাগ করে, আর ইচ্ছে করে গড়ানো case-এ থাকে// falls throughcomment।- n-টা pass-এর জন্য while loop test করে n + 1 বার, আর body একবারও না চলতে পারে;
do...whilebody অন্তত একবার চালায়। - For loop-এর অংশগুলো খালি রাখা যায়, আর
for (;;)চলে একটাbreakনা আসা পর্যন্ত;for...ofদেয় value,for...inদেয় key, string হিসেবে। breakবের হয় সবচেয়ে ভিতরের loop বা switch থেকে,continueচলে যায় পরের pass-এ, আর label থাকলে দুইটাই বাইরের loop পর্যন্ত পৌঁছাতে পারে।- আরও গভীরে: CP আর Interview Pack, nested loop, আগেভাগে বের হওয়া আর bug gallery (Pro)।
এরপর lesson 03 এই statement-গুলো কাজে লাগাবে সাতটা পুরো program-এ, FizzBuzz থেকে prime sieve পর্যন্ত।
lesson ২ শেষ
শেষ হলে চিহ্ন দিন, অগ্রগতি আপনার সাথে থাকবে।
পরেরটা: পুরো program: FizzBuzz থেকে prime sieve