Module ৩ · string আর template literal
পুরো program: কাজের মাঝে string
এই lesson-এ যা শিখবে
- Judge-এর starter-এর উপর ছয়টা পুরো program লিখতে পারবে, যেগুলো text ভেঙে আবার নতুন করে জোড়া লাগায়: word counter থেকে শুরু করে print করা রসিদ পর্যন্ত।
- বুঝিয়ে বলতে পারবে quote-এর ভেতরের comma পেলে
split(",")কেন ভুল করে, আর word counter-এ কেনfilter(Boolean)লাগে, palindrome check-এ কেনjoin("")লাগে। - Input যখন space-ওয়ালা text, তখন starter-এর lines variant বেছে নিতে পারবে, আর template literal,
padEndআরpadStartদিয়ে output-এর কলাম সোজা করে সাজাতে পারবে।
Amara-র একটা ছোট বইয়ের blog আছে, সাথে একটা দোকানও। প্রতিটা post-এর title থেকে একটা web address বানাতে হয়, editor-এ word count দেখাতে হয়, আর প্রতিটা order-এ একটা রসিদ print হয়। প্রতিটা feature-এর নিচে বসে আছে ছোট একটা program, যেটা একটা string ভেঙে নতুন একটা string বানায়। এই lesson-এ আমরা এরকম ছয়টা লিখব, প্রতিটা মোটামুটি তিরিশ লাইনের, word counter থেকে রসিদ পর্যন্ত।
Starter, তার lines variant-এ
এখানকার প্রতিটা program input পড়ে Module 1-এর fixed starter দিয়ে। বেশিরভাগই পড়ে এমন text যার ভিতরে space আছে, যেমন একটা title বা একটা বাক্য। Token starter এই text-কে শব্দে শব্দে কেটে ফেলত, space-গুলো হারিয়ে যেত। তাই এই program-গুলো ব্যবহার করে lines variant, যেখানে ঠিক দুইটা লাইন বদলায়।
Lines variant, আর এই lesson-এর মূল টুকরোগুলো
const lines = input.split("\n");
const next = () => lines[at++];
text.split(" ").filter(Boolean)
text.split("").reverse().join("")
text.charCodeAt(i) String.fromCharCode(code)
`${value}`.padStart(width) name.padEnd(width)
- প্রথম দুইটা লাইন token-এর split আর token-এর reader-এর জায়গা নেয়, তাই
next()পুরো একটা লাইন ফেরত দেয়, খালি লাইন হলেও। split(" ").filter(Boolean)space-এ কাটে, আর খালি টুকরোগুলো ফেলে দেয়।split(""),reverse()আরjoin("")text-কে character-এ কাটে, উল্টে দেয়, তারপর আবার জোড়া লাগায়।charCodeAt(i)একটা character-এর code দেয়;String.fromCharCode(code)code থেকে আবার character-এ ফেরে।padStartআরpadEndবাঁয়ে বা ডানে space বসিয়ে text-কেwidthcharacter লম্বা করে।
এখন থেকে output-এর প্রতিটা লাইন একটা template literal, lesson 02-এ যেমন দেখেছ, কোনো +-এর লম্বা শিকল ছাড়া।
শব্দ গোনা
Editor-এর হিসাবে শব্দ মানে পাশাপাশি কয়েকটা character, যার ভিতরে কোনো space নেই। প্রতিটা space-এ কাটলে প্রায় কাজ হয়ে যায়, কিন্তু পরপর দুইটা space মাঝখানে একটা খালি টুকরো রেখে যায়, খালি লাইনও তাই করে। filter(Boolean) সেই টুকরোগুলো ফেলে দেয়, কারণ "" falsy।
নতুন যা: lines variant, আর পুরো একটা লাইনের উপর split(" ").filter(Boolean)। Program-টা একটা draft-এর n-টা লাইন পড়ে, তারপর মোট কয়টা শব্দ আর সবচেয়ে লম্বা শব্দ কোনটা, সেটা জানায়। ভিতরের loop-টা হলো for-of loop, যেটা Module 4 শেখাবে: array-র প্রতিটা শব্দে সে একবার করে যায়।
const input = require("fs").readFileSync(0, "utf8");
const lines = input.split("\n");
let at = 0;
const next = () => lines[at++];
const nextInt = () => Number(next());
const out = [];
const n = nextInt();
let total = 0;
let longest = "";
for (let i = 0; i < n; i++) {
const words = next().split(" ").filter(Boolean);
total += words.length;
for (const word of words) {
if (word.length > longest.length) {
longest = word;
}
}
}
out.push(`lines: ${n}`);
out.push(`words: ${total}`);
out.push(`longest: ${longest} (${longest.length} characters)`);
console.log(out.join("\n"));
lines: 4
words: 8
longest: Template (8 characters)
এই output-টা input 4 আর তারপরের চারটা লাইনের জন্য। লাইনগুলো হলো: মাঝখানে দুইটা space-ওয়ালা একটা বাক্য, একটা খালি লাইন, তিনটা space দিয়ে শুরু হওয়া একটা লাইন, আর save time। খালি লাইনে শব্দ 0টা, আর শুরুর space-গুলো কোনো শব্দ হিসেবে গোনা হয়নি। Template আর literals দুটোতেই 8টা character; > প্রথমে যেটা পায়, সেটাই রাখে।
Palindrome, দুই ভাবে
Palindrome মানে যেটা উল্টো দিক থেকে পড়লেও একই, যেমন noon। একটা বাক্যও palindrome হতে পারে, যদি বড় হাতের অক্ষর আর space বাদ দিয়ে দেখো। দেখার উপায় দুইটা: method দিয়ে text উল্টে মিলিয়ে দেখা, অথবা দুই মাথা থেকে ভিতরের দিকে হেঁটে জোড়ায় জোড়ায় মেলানো।
নতুন যা: split(""), reverse() আর join("") এক শিকলে, আর সেই loop যেটা i ঘরকে মেলায় length - 1 - i ঘরের সাথে।
const input = require("fs").readFileSync(0, "utf8");
const lines = input.split("\n");
let at = 0;
const next = () => lines[at++];
const nextInt = () => Number(next());
const out = [];
const phrase = next();
const clean = phrase.toLowerCase().split(" ").join("");
const reversed = clean.split("").reverse().join("");
let same = true;
for (let i = 0; i < clean.length / 2; i++) {
if (clean[i] !== clean[clean.length - 1 - i]) {
same = false;
}
}
out.push(`cleaned: ${clean}`);
out.push(`reversed: ${reversed}`);
out.push(`by reverse: ${clean === reversed ? "yes" : "no"}`);
out.push(`by loop: ${same ? "yes" : "no"}`);
console.log(out.join("\n"));
cleaned: neveroddoreven
reversed: neveroddoreven
by reverse: yes
by loop: yes
এই output-টা input Never odd or even-এর জন্য। split(" ").join("") space-গুলো সরিয়ে দেয়: প্রতিটা space-এ কাটো, তারপর কিছু না দিয়ে জোড়া দাও। Input Kenji was here দিলে দুইটা check-ই বলে no। Method-এর শিকলটা পড়তে ছোট। Loop-টা দ্বিতীয় কোনো string বানায় না, শুধু মাঝখান পর্যন্ত হাঁটে, আর এই idea-টাকেই lesson 06 two-pointer pattern বানাবে।
Character code দিয়ে Caesar shift
Caesar shift প্রতিটা অক্ষরকে বর্ণমালায় নির্দিষ্ট কয়েক ঘর সামনে সরিয়ে দেয়: shift 3 হলে a হয়ে যায় d। কৌশলটা হলো number নিয়ে কাজ করা। Lesson 02-এর code table-এ A থেকে Z আছে 65 থেকে 90-এ, আর a থেকে z 97 থেকে 122-এ। C track-এর ASCII table-এও ঠিক এই সংখ্যাগুলোই।
তাই code - 97 একটা ছোট হাতের অক্ষরকে বর্ণমালায় তার ঘর বানায়, 0 থেকে 25। Shift যোগ করো, % 26 নাও যাতে 26 ঘুরে 0 হয়ে যায়, তারপর 97 আবার যোগ করো। 13 ঘরের shift-এর নাম ROT13, আর এটা নিজেই নিজেকে উল্টে দেয়।
নতুন যা: প্রতিটা character-এর উপর loop চালিয়ে charCodeAt আর String.fromCharCode, বড় হাতের আর ছোট হাতের অক্ষর আলাদা করে সামলানো, আর বাকি সব হুবহু রেখে দেওয়া।
const input = require("fs").readFileSync(0, "utf8");
const lines = input.split("\n");
let at = 0;
const next = () => lines[at++];
const nextInt = () => Number(next());
const out = [];
const n = nextInt();
for (let i = 0; i < n; i++) {
const text = next();
let result = "";
for (let j = 0; j < text.length; j++) {
const code = text.charCodeAt(j);
if (code >= 65 && code <= 90) {
result += String.fromCharCode((code - 65 + 13) % 26 + 65);
} else if (code >= 97 && code <= 122) {
result += String.fromCharCode((code - 97 + 13) % 26 + 97);
} else {
result += text[j];
}
}
out.push(result);
}
console.log(out.join("\n"));
Jul qvq Obo pebff gur ebnq?
To get to the other side!
এই output-টা input 2, তারপর একটা ধাঁধা আর ROT13-এ লেখা তার উত্তরের জন্য। একই program প্রশ্নটা লুকিয়েছে, উত্তরটা খুলে দিয়েছে। Space আর ? যেমন ছিল তেমনই গেছে, কারণ ওদের code দুইটা range-এর কোনোটাতেই পড়ে না।
13-এর shift কখনো 0-এর নিচে নামে না। Negative shift নামতে পারে, আর তখন কী গড়বড় হয়, সেটা Module 1-এর %-এর নিয়ম থেকেই আন্দাজ করা যায়। নিচের brain teaser তোমাকে সেটা খুঁজে বের করতে বলবে, আর অনুশীলন 2-এ fix-টা লাগবে।
সাধারণ একটা CSV লাইন ভাঙা
CSV মানে comma-separated values: সাদামাটা text-এ একটা table, যেটা যেকোনো spreadsheet export করতে পারে। প্রতি লাইনে একটা record, field-গুলো comma দিয়ে আলাদা। সাধারণ লাইনের জন্য split(",")-ই পুরো parser। তারপর trim() সরিয়ে দেয় comma-র পরে মানুষ যে space টাইপ করে, সেগুলো।
নতুন যা: split(","), সাথে প্রতিটা field-এ trim(), আর এমন একটা record যেটা এই সাধারণ parser ভুল পড়ে।
const input = require("fs").readFileSync(0, "utf8");
const lines = input.split("\n");
let at = 0;
const next = () => lines[at++];
const nextInt = () => Number(next());
const out = [];
const n = nextInt();
for (let i = 0; i < n; i++) {
const parts = next().split(",");
const fields = [];
for (const part of parts) {
fields.push(part.trim());
}
out.push(`${fields.length} fields: ${fields.join(" | ")}`);
}
console.log(out.join("\n"));
3 fields: Zara | 14 | Dhaka
3 fields: Bob | 15 | Sylhet
4 fields: "Maria" | 15 | "Flat 3 | Green Road"
এই output-টা input 3 আর উপরের তিনটা record-এর জন্য। প্রথম দুইটা ঠিক আছে, বাড়তি space থাকা সত্ত্বেও। তৃতীয়টা ভুল। কোনো field-এ comma থাকলে CSV সেটাকে double quote-এ রাখে, আর split quote-এর কিছুই বোঝে না, তাই Maria-র ঠিকানা দুইটা field হয়ে গেছে। Lesson 04 একটা loop দিয়ে এটা ঠিক করবে।
Slug বানানোর program
Slug হলো web address-এর সেই অংশ, যেটা একটা title থেকে বানানো: Hello, World! 2026 হয়ে যায় hello-world-2026। এতে থাকে শুধু ছোট হাতের অক্ষর আর digit, তাই যেকোনো address-এ এটা নিরাপদ। বাকি যেকোনো character-এর একটানা সারি হয়ে যায় একটা hyphen, আর দুই মাথায় কোনো hyphen থাকে না।
নতুন যা: একটা character loop, যেটা অক্ষর আর digit-এর একটানা সারিগুলো শব্দ হিসেবে জমায়, তারপর join("-")। ch >= "a" && ch <= "z" test-টা কাজ করে, কারণ string-এর উপর < code মেলায়, lesson 02-এ যেমন দেখেছ।
const input = require("fs").readFileSync(0, "utf8");
const lines = input.split("\n");
let at = 0;
const next = () => lines[at++];
const nextInt = () => Number(next());
const out = [];
const title = next();
const lower = title.toLowerCase();
const words = [];
let word = "";
for (const ch of lower) {
if ((ch >= "a" && ch <= "z") || (ch >= "0" && ch <= "9")) {
word += ch;
} else if (word !== "") {
words.push(word);
word = "";
}
}
if (word !== "") {
words.push(word);
}
const slug = words.join("-");
out.push(`title: ${title}`);
out.push(`lowercase: ${lower}`);
out.push(`words: ${words.join(" ")}`);
out.push(`slug: ${slug}`);
console.log(out.join("\n"));
title: Amara's Top 10 Books (2026)!
lowercase: amara's top 10 books (2026)!
words: amara s top 10 books 2026
slug: amara-s-top-10-books-2026
এই output-টা input Amara's Top 10 Books (2026)!-এর জন্য। শেষের if শেষ শব্দটা বাঁচায়, কারণ ওর পরে আর কোনো character নেই যে ওকে শেষ করবে। amara-s দেখো: আমাদের নিয়ম apostrophe-কে একটা ভাঙন বানিয়ে দিয়েছে। অনেক slug maker apostrophe-টা মুছেই ফেলে, সেটা আরেকটা নিয়ম মাত্র, নতুন কোনো idea না।
যে রসিদের কলাম সোজা থাকে
রসিদ আসলে সাদামাটা text-এ একটা table, আর প্রতিটা কলামের চওড়া নির্দিষ্ট হতে হয়। padEnd(16) একটা নামের পরে space বসিয়ে ওকে 16 character করে, আর padStart(8) একটা number-কে 8 ঘরের ডান কিনারায় ঠেলে দেয়। দুটোই string method, তাই number-কে আগে text বানাতে হয়।
নতুন যা: শুরুর জায়গা দিয়ে indexOf call করে দ্বিতীয় space খোঁজা, slice দিয়ে লাইনটাকে তিন টুকরো করা, লম্বা নাম ছোট করা, আর নির্দিষ্ট চওড়ার কলাম।
const input = require("fs").readFileSync(0, "utf8");
const lines = input.split("\n");
let at = 0;
const next = () => lines[at++];
const nextInt = () => Number(next());
const out = [];
const WIDTH = 34;
const n = nextInt();
let total = 0;
out.push("Amara's Book Corner".padStart(26));
out.push("-".repeat(WIDTH));
for (let i = 0; i < n; i++) {
const line = next();
const a = line.indexOf(" ");
const b = line.indexOf(" ", a + 1);
const qty = Number(line.slice(0, a));
let name = line.slice(b + 1);
const price = Number(line.slice(a + 1, b));
if (name.length > 16) {
name = name.slice(0, 15) + ".";
}
const cost = qty * price;
total += cost;
out.push(`${name.padEnd(16)}${`${qty} x ${price}`.padStart(10)}${String(cost).padStart(8)}`);
}
out.push("-".repeat(WIDTH));
out.push(`${"TOTAL (Tk)".padEnd(26)}${String(total).padStart(8)}`);
console.log(out.join("\n"));
Amara's Book Corner
----------------------------------
Notebook A5 2 x 120 240
Fountain pen 1 x 450 450
Encyclopedia of. 1 x 1250 1250
----------------------------------
TOTAL (Tk) 1940
এই output-টা input 3 আর তারপরের তিনটা item-এর জন্য; প্রতিটায় আছে পরিমাণ, টাকায় দাম আর একটা নাম। নামের ভিতরে space থাকতে পারে, তাই দ্বিতীয় space-এর পরের পুরোটাই নাম। `${qty} x ${price}` হলো আরেকটা template-এর ${}-এর ভিতরে বসা একটা template: আগে মাঝের কলামটা বানায়, তারপর pad করে। 26 character-এর নামটা কেটে 15 character আর একটা dot করা হয়েছে, তাই কলামগুলো এখনো সোজা।
এটা কোথায় কাজে লাগে
- WordPress। PHP-তে লেখা ওদের
sanitize_title()function একটা post-এর title থেকে slug বানায়। Default-এ এটা call করেsanitize_title_with_dashes(), তাই "My Excellent Sentence" হয়ে যায়my-excellent-sentence: Example 5-এর idea-ই, অন্য একটা ভাষায়। - npm-এর slugify। এই JavaScript package
slugify("some string")-কে বানায়some-string।lower: trueনা দিলে বড় হাতের অক্ষর রেখে দেয়, আর কিছু চিহ্নকে শব্দে বদলে ফেলে, যেমন ♥ হয়ে যায়love। - Papa Parse। JavaScript-এর একটা CSV parser, যেটা নিজের সম্পর্কে বলে CSV-র standard RFC 4180 অনুযায়ী ঠিকঠাক কাজ করে। Example 4 যে quote-এর ভেতরের comma আর line break সামলাতে পারে না, Papa Parse সেগুলো পারে।
- Usenet আর Python-এ ROT13। 1980-এর দশকের শুরুতে Usenet newsgroup-এ মানুষ ধাঁধার উত্তর আর spoiler লুকাতে ROT13 ব্যবহার করত। Python-এর
codecsmodule এখনো এটা রাখে,rot_13text transform হিসেবে।
যে ভুলগুলো সবাই করে
১. শুধু split(" ") দিয়ে শব্দ গোনা।
const line = "Amara writes every day";
console.log(line.split(" "));
console.log(line.split(" ").length);
console.log(line.split(" ").filter(Boolean).length);
[ 'Amara', 'writes', '', 'every', 'day' ]
5
4
কোনো error নেই: দুইটা space মাঝখানে একটা খালি string রেখে যায়, আর সেটাও শব্দ হিসেবে গোনা হয়। .filter(Boolean) যোগ করো। এটা তুমি বাদ দেবে, কারণ তোমার নিজের test-এর বাক্যে space ছিল একটা করে, আর আসল text-এ সেটা কমই থাকে।
২. উল্টানো array-কে string-এর সাথে মেলানো।
const word = "anna";
const back = word.split("").reverse();
console.log(back);
console.log(back === word);
console.log(back.join("") === word);
[ 'a', 'n', 'n', 'a' ]
false
true
reverse() ফেরত দেয় একটা array, আর array কখনো একটা string-এর === হয় না। ফলে প্রতিটা শব্দকেই মনে হয় palindrome না। শিকলের শেষে join("") দাও। তুমি এটা বাদ দেবে, কারণ split আর reverse দেখেই মনে হয় কাজ শেষ।
৩. Number-এর উপর padStart call করা।
const cost = 240;
console.log("cost:", cost);
console.log("Notebook".padEnd(12) + cost.padStart(6));
cost: 240
TypeError: cost.padStart is not a function
Playground-এর verdict Runtime error, আর থামার আগে যে লাইন print হয়েছিল, সেটা থেকে যায়। padStart একটা string method, অথচ cost একটা number। লেখো String(cost).padStart(6), অথবা একটা template literal-কে pad করো। তুমি এটা ভুলবে, কারণ screen-এ number-টাকে text-এর মতোই দেখায়।
Zara ওর ক্লাসের জন্য একটা শব্দের খেলা বানাচ্ছে। খেলোয়াড়রা একটা একটা শব্দ টাইপ করে, আর খেলাটাকে বলতে হবে কোনগুলো palindrome। Zara-র প্রথম test হলো Level, কারণ সামনে বড় হাতের অক্ষর থাকলে কিছু বদলানো উচিত না।
Input. n, তারপর n-টা শব্দ। প্রতিটা শব্দ ASCII অক্ষর (a-z, A-Z) দিয়ে বানানো।
Output. প্রতিটা শব্দের জন্য এক লাইন: বড় হাতের আর ছোট হাতের অক্ষরকে একই ধরে উল্টো দিক থেকে পড়লেও একই হলে yes, নইলে no।
Constraints. 1 <= n <= 20000। প্রতিটা শব্দে 1 থেকে 50টা অক্ষর।
Sample. Input 5 আর Level noon Kenji Anna ab দিলে পাঁচ লাইনে yes, yes, no, yes আর no।
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
// Read n, then n words. Per word: yes or no.
console.log(out.join("\n"));
palindromes নামে grade হয়। শব্দগুলোতে space নেই, তাই এটা token starter। Example 2-এর যেকোনো উপায়েই পাস করবে; যেটা তুমি বুঝিয়ে বলতে পারো, সেটা নাও।
Kenji বন্ধুদের Caesar shift দিয়ে গোপন message পাঠায়, আর ওর পছন্দ বড় বড় shift: 29, -3, এমনকি -1000। যেকোনো shift সামলাতে পারে, এমন program লেখো।
Input. লাইন 1-এ k। লাইন 2-এ text। এই problem starter-এর lines variant ব্যবহার করে, আর input-এর শেষ লাইন কখনো খালি না।
Output. Text-টা, যেখানে প্রতিটা অক্ষর বর্ণমালায় k ঘর সামনে সরেছে (k negative হলে পেছনে), শেষে গিয়ে আবার শুরুতে ঘুরে, বড় হাতের অক্ষর বড় হাতেরই থেকে। বাকি প্রতিটা character যেমন ছিল তেমন থাকে।
Constraints. -1000 <= k <= 1000। Text-এ 1 থেকে 100000টা printable ASCII character (code 32 থেকে 126)।
Sample. দুই লাইনে input 3 আর Hello, Zara! xyz দিলে Khoor, Cdud! abc।
const input = require("fs").readFileSync(0, "utf8");
const lines = input.split("\n");
let at = 0;
const next = () => lines[at++];
const nextInt = () => Number(next());
const out = [];
// your code: read with next() and nextInt(), push every line of output to out
// Read k, then the text. Shift every letter k places.
console.log(out.join("\n"));
caesar-shift নামে grade হয়। Example 3 থেকে শুরু করো। Hidden test-এ negative shift আছে, 26-এর অনেক বেশি shift-ও আছে, তাই আগে brain teaser-টা সমাধান করো।
Amara পুরো blog নতুন একটা host-এ সরাচ্ছে, আর পুরনো প্রতিটা post-এর একটা slug লাগবে। কিছু title-এ কোনো অক্ষরই নেই, শুধু চিহ্ন, অথচ ওই post-গুলোরও একটা address লাগবে।
Input. n, তারপর n-টা title, প্রতি লাইনে একটা। এই problem starter-এর lines variant ব্যবহার করে, আর input-এর শেষ লাইন কখনো খালি না।
Output. প্রতিটা title-এর জন্য এক লাইনে তার slug। বানানোর নিয়ম: title-টা ছোট হাতের করো। a-z বা 0-9 না, এমন character-এর প্রতিটা সবচেয়ে লম্বা একটানা সারি হয়ে যায় একটা hyphen, আর শুরুতে বা শেষে কোনো hyphen থাকে না। কিছুই না বাঁচলে print করো untitled শব্দটা।
Constraints. 1 <= n <= 10000। প্রতিটা title-এ 1 থেকে 200টা printable ASCII character (code 32 থেকে 126)।
Sample. Input 3, তারপর তিন লাইনে Hello, World! 2026, --- Strings & Template Literals --- আর !!! দিলে hello-world-2026, strings-template-literals আর untitled।
const input = require("fs").readFileSync(0, "utf8");
const lines = input.split("\n");
let at = 0;
const next = () => lines[at++];
const nextInt = () => Number(next());
const out = [];
// your code: read with next() and nextInt(), push every line of output to out
// Read n, then n titles. Per title: its slug, or untitled.
console.log(out.join("\n"));
slug-maker নামে grade হয়। Example 5 একটা title সামলায়; এখানে title অনেক, আর কয়েকটায় একটা শব্দও বাঁচে না।
Amara-র editor phone-এর জন্য প্রতিটা post-এর একটা সরু preview দেখায়। Preview text-টাকে এমনভাবে ভাঙে যাতে কোনো লাইন screen-এর চেয়ে চওড়া না হয়, আর কোনো শব্দ কখনো মাঝখান থেকে কাটা না পড়ে।
Input. লাইন 1-এ চওড়া w। লাইন 2-এ text, শব্দগুলোর মাঝে এক বা একাধিক space।
Output. শব্দগুলো ক্রম ঠিক রেখে লাইনে লাইনে সাজানো। প্রতিটা লাইনে যতগুলো শব্দ ধরে ততগুলো, মাঝে একটা করে space, আর লাইনের দৈর্ঘ্য বড়জোর w character। w-এর চেয়ে লম্বা কোনো শব্দ পায় নিজের আলাদা একটা লাইন।
Constraints. 10 <= w <= 80। Text-এ 1 থেকে 1000টা printable ASCII character, আর অন্তত একটা শব্দ।
Sample. Input 16 আর Amara writes every day, and her readers wait for Friday. দিলে চার লাইনে Amara writes, every day, and, her readers wait আর for Friday.।
const input = require("fs").readFileSync(0, "utf8");
const lines = input.split("\n");
let at = 0;
const next = () => lines[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 হয় না। যে লাইনটা বানাচ্ছ সেটা একটা variable-এ রাখো, আর প্রতিটা শব্দের জন্য একটাই প্রশ্ন করো: সামনে একটা space সহ এটা এখনো ধরে কি? Zara-র test: 10 চওড়ায় supercalifragilistic, আর ঠিক w character-এর একটা লাইন।
সচরাচর যে প্রশ্নগুলো আসে
Palindrome check কি বাংলা শব্দে কাজ করে?
Zara চেষ্টা করে দেখেছে।
"কি".split("").reverse().join("")দেয়"িক": কার-চিহ্নটা লাফিয়ে ব্যঞ্জনের সামনে চলে যায়। অক্ষর আর তার কার-চিহ্ন মিলে দুইটা code unit, আরsplit("")ঠিক ওদের মাঝখানে কাটে। পাঠক যে character দেখে, সেগুলো নিয়ে কাজ করবে lesson 05।Loop-এর ভিতরে
result +=কি slow?এই সাইজে না। প্রতিটা
+=একটা নতুন string বানায়, তবু মানুষ যত copy-র ভয় পায়, V8 তার বেশিরভাগটাই এড়িয়ে যায়। Lesson 05 (Pro) এটাকে একটা array আর একবারেরjoin-এর সাথে মেপে দেখায়।Slug বানাতে regular expression ব্যবহার করি না কেন?
করতেই পারো। Regular expression হলো text-এর জন্য ছোট একটা pattern-এর ভাষা, আর Module 16 এটা শেখাবে। Loop-টা আগে প্রতিটা সিদ্ধান্ত সাদামাটা code-এ দেখায়, আর lesson 04 দেখাবে কখন একটা কাজ pattern হয়ে যায়।
ROT13-এর আলাদা decoder লাগে না কেন?
কারণ 13 + 13 = 26, বর্ণমালার এক পুরো চক্কর। অন্য যেকোনো shift k উল্টাতে লাগে 26 - k ঘরের shift।
মূল কথা
- Input space-ওয়ালা text হলে starter-এর lines variant নাও; তখন
next()পুরো একটা লাইন ফেরত দেয়, খালি লাইনও। split(" ").filter(Boolean)একাধিক space আর খালি লাইন পেরিয়েও ঠিকঠাক শব্দ গোনে;split,reverseআরjoinASCII text উল্টায়।charCodeAt, একটু অঙ্ক আরString.fromCharCodeমিলে Caesar shift;% 26ঘুরিয়ে আনে, আর negative shift-এ আরও এক ধাপ লাগে।split(",")শুধু সাধারণ CSV পড়তে পারে: quote-এর ভেতরে একটা comma থাকলেই ভাঙে।padEndআরpadStart-সহ template literal সোজা কলাম print করে; pad করো string-কে, কখনো number-কে না।- আরও গভীরে: CP and Interview Pack, string-এর pattern, প্রশ্ন আর bug gallery (Pro)।
এরপর lesson 04 quote বোঝে এমন একটা loop দিয়ে Kenji-র CSV import ঠিক করে। তারপর judgement call-গুলো নেয়: method না loop, template না +, আর কখন কাজটা regular expression হয়ে গেছে।
lesson ৩ শেষ
শেষ হলে চিহ্ন দিন, অগ্রগতি আপনার সাথে থাকবে।
পরেরটা: কোনটা কখন: method না loop, template না +, আর কখন regex