Module ৩ · কনস্ট্যান্ট, qualifier, ইনপুট আর আউটপুট
Problem: পড়া আর ছাপানো
এই lesson-এ যা শিখবে
- Starter-র দেওয়া format দিয়ে judge-র input পড়তে পারবে, আর ও কী ফেরত দিল সেটা যাচাই করতে পারবে।
- এমন উত্তর ছাপতে পারবে, যার প্রতিটা ফাঁকা জায়গা আর অঙ্ক statement যেখানে বলেছে ঠিক সেখানেই।
ifছাড়াই হ্যাঁ বা না প্রশ্নের উত্তর দিতে পারবে, তুলনাটাকেই ছেপে দিয়ে।
দশটা problem, লুকানো test দিয়ে graded। এর আটটার সাথে পাঁচটা lesson-র ভিতরেই তোমার দেখা হয়েছে। দুইটা নতুন।
গত সেটটা ছিল type বাছাই নিয়ে। এটা judge-র সাথে কথা বলার দুই অর্ধেক নিয়ে। মানগুলো ভিতরে আনা, আর ঠিক যে চেহারায় চাওয়া হয়েছে সেই চেহারায় উত্তর বের করা।
গত problem সেটের পর নতুন কী
Module 2-তে প্রতিটা উত্তর ছিল একটা সংখ্যা। এখানে অর্ধেক উত্তরই কয়েক লাইন, width সহ, আর একটা ফাঁকা জায়গা ভুল হলেই wrong answer।
দশটার চারটা সাজানো নিয়ে। ঠিক চওড়ার একটা ঘর, ঠিক জায়গায় একটা দশমিক বিন্দু, আর এমন একটা শূন্য যেটা বাদ না দিয়ে ছাপতেই হবে।
তিনটা একটা পড়ার ফেরত পাওয়া গোনা নিয়ে। Module 2 ওটার কথা তোলেনি, কারণ সেখানকার প্রতিটা input আসার কথা দেওয়া ছিল।
তাই গল্পের আগে প্রতিটা statement-র Output অংশটা পড়ো। ওটাই নির্দেশনা, আর গল্পটা কেবল এজন্য যাতে কোন problem ছিল সেটা তোমার মনে থাকে।
এখনো if নেই, loop নেই আর ভাগশেষ নেই
এই module operator-র আগে আর সিদ্ধান্তের আগে। নিচের কোনোটাতেই if, for, while, শর্তসূচক ? বা % operator লাগে না।
একটা problem জোড়া হ্যাঁ বা না প্রশ্ন করে, আর উত্তরটা %d দিয়ে ছাপা একটা তুলনা। Lesson 5 দেখিয়েছিল তুলনা একটা expression, যার মান 1 বা 0।
দুইটা problem পূর্ণ পয়সায় টাকার হিসাব করে আর দশমিক বিন্দুটা printf দিয়ে ফিরিয়ে আনে, যার জন্য ভাগ আর বিয়োগ ছাড়া কিছুই লাগে না।
যদি দেখো এমন কিছুর দিকে হাত বাড়াচ্ছ যেটার সাথে তোমার দেখাই হয়নি, তাহলে problem-টা তোমাকে সামনে তাকাতে না, একটা lesson আবার পড়তে বলছে।
প্রতিটা starter-এ পড়াগুলো আগেই লেখা
প্রতিটা graded problem শুরু হয় তোমার জন্য লেখা একটা scanf লাইন দিয়ে, ঠিক format-এ, ampersand সহ। ওটায় হাত দিয়ো না।
এটা উদারতা না। Lesson 4-র ফাঁদগুলো এমন, যেগুলোর সাথে একবার দেখা হলে তুমি সারাজীবন ওদের এড়িয়ে চলো, আর judge ওদের সাথে দেখা করার জায়গা না। পড়ার পরে যা ঘটে সেটাই তোমার কাজ।
দুইটা starter নামের জন্য char-র একটা array-ও declare করে। Array Module 9-র বিষয়, তাই char name[20]-কে পাশাপাশি বিশটা বাক্স ধরো আর নামটা একটা %s-এ ব্যবহার করো।
এই দশটা problem-র যে specifier লাগে
printf("%d\n", n) একটা int
printf("%u\n", n) একটা unsigned int
printf("%lld\n", n) একটা long long
printf("%10u\n", n) ওটাই, দশ চওড়া একটা ঘরে
printf("%10x\n", n) %10X ছোট আর বড় হাতের base 16
printf("%10o\n", n) base 8
printf("%-12s%5d\n", s, n) বাঁয়ে সাজানো নাম, তারপর ডানে সাজানো সংখ্যা
printf("%lld.%02lld\n", t, p) পূর্ণ টাকা, একটা বিন্দু, দুই অঙ্কের পয়সা
printf("VAT %d%%\n", pc) %% একটা শতাংশ চিহ্ন ছাপে
scanf("%d %d", &a, &b) দুইটা int
scanf("%u", &n) একটা unsigned int
scanf("%lld", &n) একটা long long
scanf("%x %o", &h, &o) base 16 তারপর base 8-র সংখ্যা
scanf("%19s", name) একটা শব্দ, বড়জোর 19 অক্ষর, ampersand নেই
%02lldদুই অঙ্কে ভরাট করে, আর এভাবেই 5 পয়সা05হয়ে ছাপে।- Width সবচেয়ে কম কতটুকু। ঘরের চেয়ে চওড়া মান বাইরে বেরিয়ে যায়, আর সেটাই ঠিক।
- এখানে প্রতিটা পড়া একটা গোনা ফেরত দেয়, আর তিনটা problem সেই গোনাটাকে উত্তরের অংশ হিসেবে ছাপে।
Submit করার আগে কীভাবে পরীক্ষা করবে
চারটা যাচাই, আর দ্বিতীয়টাই সাজানোর bug ধরে।
- Sample চালাও। Sample ফেল করলে বাকি কিছুরই আর মানে নেই।
- তোমার প্রথম লাইনের অক্ষর গোনো sample-র প্রথম লাইনের সাথে মিলিয়ে। শব্দ না, অক্ষর।
- Constraint-র দুই প্রান্তেই চালাও। Statement থেকে সবচেয়ে বড় বৈধ input তুলে এনে বসিয়ে দাও।
- ফাঁকা input চালাও যেখানে statement সেটা মানে, কারণ এই দশটার দুইটায় কিছুই না থাকা একটা test আছে।
তাই পরীক্ষা করা মানে program আবার পড়া না। মানে statement আগেই যেসব input-র কথা বলে দিয়েছে, সেগুলো দিয়ে ওটা চালানো।
Hint-র সিঁড়ি
নিচের প্রতিটা problem-এ তিনটা ধাপ আছে, যেগুলো তুমি ক্রম ধরে খোলো। Hint 1 বলে কোনটা খেয়াল করতে হবে, Hint 2 কথায় পথটা বলে, আর Solution দুই অনুচ্ছেদে পুরো পদ্ধতিটা বোঝায়।
Hint খোলার হিসাব রাখা হয় আর তাতে তোমার কিছুই যায় আসে না। তারপর program-টা নিজের হাতে টাইপ করো, কারণ পড়াটা দক্ষতা না।
এই দশটার তিনটার গড়ন এটাই। scanf যা ফেরত দিল সেটা রেখে দাও, তারপর মানগুলোর পাশে ছেপে দাও।
#include <stdio.h>
int main(void)
{
int quantity = 0;
int price = 0;
int read = scanf("%d %d", &quantity, &price);
printf("read %d\n", read);
printf("quantity %d\n", quantity);
printf("price %d\n", price);
return 0;
}
read 2
quantity 12
price 4500
ওই output-টা 12 4500 input-র জন্য। কেবল 12 দাও, প্রথম লাইনটা হবে 1 আর তৃতীয়টা তখনো declaration-র 0 ছাপবে।
invoice-exact-র একটা ছোট রূপ। এখানকার প্রতিটা width statement থেকে এসেছে, রুচি থেকে না।
#include <stdio.h>
int main(void)
{
const int VAT_PERCENT = 15;
printf("%-12s%5s%10s\n", "ITEM", "QTY", "PAISA");
printf("%-12s%5d%10lld\n", "rice", 12, 54000LL);
printf("---------------------------\n");
printf("VAT %d%%%10s%10lld\n", VAT_PERCENT, "", 8100LL);
printf("%-12s%5s%10lld\n", "TOTAL", "", 62100LL);
return 0;
}
ITEM QTY PAISA
rice 12 54000
---------------------------
VAT 15% 8100
TOTAL 62100
VAT লাইনটা বাকিগুলোর চেয়ে আলাদা ভাবে বানানো, কারণ ওর label-এ একটা সংখ্যা আছে। VAT 15% সাত অক্ষরের, তাই পরের ফাঁকা %10s মোট সতেরোতে নিয়ে যায় আর কলামগুলো মিলেই থাকে।
এই সেটের দুইটা টাকার problem-ই ঠিক এটাই করে। কোথাও কোনো দশমিক type জড়ায় না।
#include <stdio.h>
int main(void)
{
const long long VAT_PERCENT = 15;
const long long PAISA_PER_TAKA = 100;
const long long PERCENT_WHOLE = 100;
long long subtotal = 23310;
long long vat = subtotal * VAT_PERCENT / PERCENT_WHOLE;
printf("vat paisa : %lld\n", vat);
printf("vat taka : %lld.%02lld\n", vat / PAISA_PER_TAKA,
vat - vat / PAISA_PER_TAKA * PAISA_PER_TAKA);
return 0;
}
vat paisa : 3496
vat taka : 34.96
সত্যিকারের উত্তর 3496.5 পয়সা আর ভাগটা অর্ধেকটা ফেলে দিয়েছে, আর statement-গুলো "ভগ্নাংশ বাদ" বলতে এটাই বোঝায়।
দ্বিতীয় লাইনটা % operator ছাড়াই পয়সাটা বের করে: ভাগ করো, আবার গুণ করো, বিয়োগ করো। Module 2-র lesson 2-র অনুশীলন 4 এই ভাবনাটাই বানিয়েছিল।
এটা কোথায় কাজে লাগে
- প্রতিটা programming contest। ICPC, Codeforces আর Progsity-র contest platform সবাই output অক্ষরে অক্ষরে বিচার করে। যে problem তুমি ঠিক বলে বিশ্বাস করো তাতে "test 4-এ wrong answer" মানে প্রায় সবসময়ই একটা width বা একটা দশমিক ঘর।
- একটা point of sale terminal। দোকানের ছাপা receipt-র কলাম নির্দিষ্ট, যাতে till roll পড়া যায়। আর অঙ্কগুলো সবচেয়ে ছোট এককে গোনা হয়, Module 2-র lesson 3 যে কারণ দিয়েছিল সেই কারণেই।
- Golden file দিয়ে পরীক্ষা। Compiler আর command line tool চালিয়ে তাদের output জমা রাখা একটা file-র সাথে মেলানো হয়। GCC-র নিজের test suite ঠিক এই লুকানো test-গুলোর মতোই কাজ করে।
- এই track-র স্বয়ংক্রিয় মূল্যায়ন। পরের প্রতিটা module-র graded অনুশীলন আর Skill Test-র build অংশ এই দশটা problem-র judge-ই ব্যবহার করে।
যে ভুলগুলো সবাই করে
১. একটা prompt ছেপে দেওয়া।
printf("Enter two numbers: ");
scanf("%d %d", &a, &b);
কোথাও কিছু বলা হয় না, আর মানুষ টাইপ করলে এটা সাহায্যই করে। Judge তোমার ছাপা প্রতিটা অক্ষর মেলায়, তাই prompt-টাও তোমার উত্তরের অংশ আর তোমার উত্তরটা ভুল। Submit করার আগে prompt সরিয়ে ফেলো।
২. টাকার হিসাবে ভরাটের শূন্যটা বাদ দেওয়া।
printf("%lld.%lld\n", taka, paisa);
কিছুই বলে না, আর পয়সা দশ বা তার বেশি হলে প্রতিটা test-ই পাশ করে। 1200 টাকা 5 পয়সার জের 1200.05-র বদলে 1200.5 হয়ে ছাপে। ওটা %02lld।
৩. যে পড়া মানগুলো বদলে দিল, তার আগেই ওগুলো ছেপে দেওয়া।
int first = scanf("%d %d", &a, &b);
int second = scanf("%d %d", &a, &b);
printf("%d %d %d\n", first, a, b);
কিছুই বলে না, আর লাইনটা বৈধ C। ও প্রথম পড়ার গোনাটা দ্বিতীয় পড়ার মানের পাশে বসিয়ে দেয়, কারণ দুইটা পড়াই একই দুইটা বাক্সে লেখে। পরের পড়া চালু হওয়ার আগেই প্রতিটা লাইন ছেপে ফেলো।
৪. মানটাকে ঘরের চওড়ায় কেটে আনতে চাওয়া।
printf("%.10u\n", n);
কিছুই বলে না, আর লেখক যা আশা করেছিল ওটা তা করে না। Width কখনো মান কাটে না, আর integer-এ precision বরং শূন্য দিয়ে ভরাট করে। Statement যদি বলে ঘরটা দশ চওড়া, তাহলে এগারো অঙ্কের মানের বাইরে বেরিয়ে যাওয়াই উদ্দেশ্য।
Kenji একটা calculator-র সবচেয়ে সহজ দুইটা button পরীক্ষা করছে, আর সংখ্যাগুলো এত বড় যে দ্বিতীয় উত্তরটা প্রথমটার জায়গায় আঁটবে না।
Input. এক লাইনে দুইটা পূর্ণসংখ্যা a আর b।
Output. দুই লাইন: যোগফল, তারপর গুণফল।
Constraints. -100000 <= a, b <= 100000।
Sample. Input 3 4 দিলে 7 তারপর 12।
#include <stdio.h>
int main(void)
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
/* Two printf calls. The product does not fit in an int. */
return 0;
}
Run in Compiler
Hint 1
সবচেয়ে বড় বৈধ গুণফল দশ বিলিয়ন। একটা int দুই বিলিয়ন পেরিয়েই থেমে যায়।
Hint 2
গুণ হওয়ার আগেই এক পাশ চওড়া করে নাও, তারপর ফলটা %lld দিয়ে ছাপো।
Solution
যোগফল int-এ আঁটে, তাই ওটা %d দিয়ে ছাপো, আর কিছু না। গুণফলের জন্য long long লাগে, আর গুণটাও চওড়া type-এ হতে হবে: লেখো (long long)a * b, cast-টা গোটা জিনিসটার চারপাশে না, এক পাশে।
গোটা expression-র চারপাশে cast, মানে (long long)(a * b), আগে int-এ গুণফল বের করে তারপর ধ্বংসাবশেষটা চওড়া করে। দুইটা বানানই ছোট test-গুলো পাশ করে, আর সবচেয়ে বড়টা কেবল প্রথমটাই পাশ করে।
Amara-র config file permission লেখে base 8-এ আর রঙ লেখে base 16-এ। দুইটাই decimal সংখ্যা হিসেবে ছাপো।
Input. এক লাইনে একটা hexadecimal সংখ্যা তারপর একটা octal সংখ্যা, কোনো prefix ছাড়া।
Output. এক লাইনে দুইটাই decimal-এ, মাঝে একটা ফাঁকা জায়গা।
Constraints. Hex 0 থেকে FFFFFF, যেকোনো হাতের অক্ষরে; octal 0 থেকে 7777777।
Sample. Input 1F 755 দিলে 31 493।
#include <stdio.h>
int main(void)
{
unsigned int from_hex = 0;
unsigned int from_octal = 0;
scanf("%x %o", &from_hex, &from_octal);
/* One printf. Both boxes already hold ordinary numbers. */
return 0;
}
Run in Compiler
Hint 1
রূপান্তরটা scanf-র ভিতরেই হয়ে গেছে। বদলানোর মতো আর কিছু বাকি নেই।
Hint 2
একটা printf, দুইটা %u specifier আর মাঝে একটামাত্র ফাঁকা জায়গা।
Solution
Base হলো সংখ্যা লেখার একটা পদ্ধতি, সংখ্যার নিজের কোনো গুণ না। %x লেখাটাকে base 16 ধরে পড়েছে আর %o base 8 ধরে, আর প্রতিটা variable-এ গিয়ে বসেছে সাধারণ একটা মান। ওটা %u দিয়ে ছাপলে base 10-এ লেখা হয়, আর program এটুকুই।
Variable দুইটা int না হয়ে unsigned int, কারণ %x আর %o unsigned মানের জন্য সংজ্ঞায়িত। সবচেয়ে বড় বৈধ hex মানটা range-র অনেক ভিতরে, তাই কিছুই উপচে পড়ে না। দুইটা গুলিয়ে ফেললে local build-এ একটা warning আসত আর Playground-এ কিছুই আসত না।
Kenji-র exam hall-এ প্রতি block-এ 12টা সারি আর প্রতি সারিতে 8টা আসন। Block আর booked আসন পড়ো, তারপর তিনটা মোট ছাপো।
Input. এক লাইনে দুইটা পূর্ণসংখ্যা: block-র সংখ্যা, তারপর আগে থেকে booked আসন।
Output. তিন লাইন: rows, capacity আর free, প্রতিটার পরে একটা ফাঁকা জায়গা আর সংখ্যাটা।
Constraints. 0 <= block <= 10000, 0 <= booked <= capacity। 12 আর 8 একবার করে থাকবে, নাম দেওয়া constant হিসেবে।
Sample. Input 3 71 দিলে rows 36, capacity 288, free 217।
#include <stdio.h>
int main(void)
{
const int SEATS_PER_ROW = 8;
const int ROWS_PER_BLOCK = 12;
int blocks = 0;
int booked = 0;
scanf("%d %d", &blocks, &booked);
/* Three printf calls. Every number in them comes from a name. */
return 0;
}
Run in Compiler
Hint 1
আগে সারি, তারপর সারি থেকে capacity, তারপর capacity থেকে free।
Hint 2
মাঝখানে দুইটা variable রাখলে তিনটা লাইন নিজেরাই পড়া যায়। সবচেয়ে বড় capacity 960000, একটা int-র অনেক ভিতরে।
Solution
Block-কে সারির constant দিয়ে গুণ করে সারির সংখ্যা পাও। ওটাকে আসনের constant দিয়ে গুণ করে capacity, তারপর booked আসন বাদ দাও। তিনটা printf, %d সহ, আর শব্দগুলো statement যেভাবে লিখেছে হুবহু সেভাবে।
Judge তোমার output পড়ে আর তোমার constant দেখতে পায় না, তাই নাম দেওয়ার নিয়মটা তোমার নিজের হাতে। একবার খালি সংখ্যা দিয়ে লেখো, তারপর গুনে দেখো সারিতে নয়টা আসন দিয়ে hall বানালে কয়টা লাইনে হাত দিতে হতো। ওই সংখ্যাটাই lesson 1 থাকার পুরো কারণ।
Maria-র till, যেখানে VAT-র হার ঠিক এক লাইনে থাকে। একটা পরিমাণ আর পয়সায় প্রতি এককের দাম পড়ো।
Input. এক লাইনে দুইটা পূর্ণসংখ্যা: পরিমাণ, তারপর পয়সায় প্রতি এককের দাম।
Output. তিন লাইন, প্রতিটায় একটা শব্দ তারপর অঙ্কটা পূর্ণ টাকা, একটা দাঁড়ি-চিহ্ন আর দুই অঙ্কের পয়সা হিসেবে।
Constraints. 1 <= পরিমাণ <= 100000, 1 <= প্রতি এককের দাম <= 10000000, VAT 15 শতাংশ আর পয়সার ভগ্নাংশ বাদ। কোনো double না।
Sample. Input 3 12000 দিলে Subtotal 360.00, VAT 54.00, Total 414.00।
#include <stdio.h>
int main(void)
{
const long long VAT_PERCENT = 15;
const long long PAISA_PER_TAKA = 100;
const long long PERCENT_WHOLE = 100;
long long quantity = 0;
long long unit_paisa = 0;
scanf("%lld %lld", &quantity, &unit_paisa);
/* Three lines. %02lld is what makes five paisa print as 05. */
return 0;
}
Run in Compiler
Hint 1
শেষ মুহূর্ত পর্যন্ত সবকিছুই পয়সা। দশমিক বিন্দুটা printf-র সমস্যা, অঙ্কের না।
Hint 2
টাকা মানে পয়সাকে একশো দিয়ে ভাগ। বাকি পয়সা মানে মোট থেকে টাকা গুণ একশো বাদ।
Solution
Subtotal মানে পরিমাণ গুণ প্রতি এককের দাম। VAT মানে subtotal গুণ শতাংশ ভাগ একশো, আর total মানে দুইটার যোগ। তিনটাই long long, কারণ এখানে সবচেয়ে বড় subtotal হাজার বিলিয়ন পয়সা।
প্রতিটা লাইন দুইটা সংখ্যা ছাপে। টাকাটা আসে একশো দিয়ে পূর্ণসংখ্যার ভাগ থেকে, আর পয়সাটা আসে মোট থেকে টাকা গুণ একশো বাদ দিয়ে। দ্বিতীয়টার জন্য %02lld লাগে, যাতে দশের কম মানও তার শুরুর শূন্যটা ছাপে। একটা লুকানো test এক পয়সা দামের একটাই জিনিস কেনে, যেখানে VAT দাঁড়ায় শূন্যে আর প্রতিটা লাইনই এক টাকার ভগ্নাংশ।
Zara-র sign-in desk-এ নামের ঘরটা উনিশ অক্ষর চওড়া, আর কোনো একদিন কেউ এর চেয়ে লম্বা নাম লিখবেই।
Input. বড়জোর এক লাইন, তাতে ফাঁকা জায়গা ছাড়া একটা শব্দ। ফাঁকাও হতে পারে।
Output. দুই লাইন: Hello, <নাম>! তারপর read আর scanf যা ফেরত দিল।
Constraints. শব্দটা 1 থেকে 19 অক্ষরের। ফাঁকা input -1 ফেরত দেয় আর ফাঁকা নামকে শুভেচ্ছা জানায়।
Sample. Input Maria দিলে Hello, Maria! তারপর read 1।
#include <stdio.h>
int main(void)
{
char name[20] = {0};
int read = scanf("%19s", name);
/* Two lines: the greeting, then what scanf gave back. */
return 0;
}
Run in Compiler
Hint 1
শুভেচ্ছাটা একটা printf, কমা আর বিস্ময়চিহ্নের মাঝে একটা %s বসিয়ে।
Hint 2
দ্বিতীয় লাইনটা read-এ আগে থেকেই বসে থাকা মানটা ছাপে। ফাঁকা input-এ ওই মানটা -1 আর নামটা তখনো ফাঁকা।
Solution
দুইটা printf, আর কিছু না। প্রথমটা লেখে Hello, , তারপর নামটা %s দিয়ে, তারপর একটা বিস্ময়চিহ্ন। দ্বিতীয়টা লেখে read শব্দটা, একটা ফাঁকা জায়গা আর গোনাটা %d দিয়ে।
দুইটা লুকানো test-ই এই problem-র মূল কথা। একটা পাঠায় ঠিক 19 অক্ষরের নাম, যেটা starter-র declare করা বাক্সগুলো ভরে ফেলে আর প্রমাণ করে format-র 19-টা কিছু একটা করছিল। অন্যটা কিছুই পাঠায় না, তাই scanf -1 ফেরত দেয়, array-টা তখনো পুরো শূন্য, আর %s কমা আর বিস্ময়চিহ্নের মাঝে কিছুই ছাপে না।
Kenji একটা device register পড়ছে আর ওটা তিনটা base-এ চায়, প্রতিটা একই দশ চওড়া ঘরে বসানো।
Input. এক লাইনে decimal-এ লেখা একটা পূর্ণসংখ্যা n।
Output. চার লাইন: dec:, hex:, HEX: আর oct:, প্রতিটার পরে n একটা 10 চওড়া ঘরে।
Constraints. 0 <= n <= 4294967295।
Sample. Input 255 দিলে dec: 255 আর আরও তিন লাইন।
#include <stdio.h>
int main(void)
{
unsigned int n = 0;
scanf("%u", &n);
/* Four lines, four bases, one width. */
return 0;
}
Run in Compiler
Hint 1
চারটা printf, প্রতিটায় একটা করে অক্ষরের তফাত। Label চার অক্ষরের, তারপরই ঘরটা শুরু।
Hint 2
বড় হাতের X বড় হাতের অঙ্ক দেয়। Width বসে শতাংশ চিহ্ন আর conversion অক্ষরের মাঝে।
Solution
চারটা label সাধারণ লেখা হিসেবে ছাপো, আর প্রতিটার পরে একই variable আলাদা conversion দিয়ে: %10u, %10x, %10X আর %10o। কোনো রূপান্তর করার নেই আর দ্বিতীয় কোনো variable রাখারও নেই।
Range-র একদম উপরের লুকানো test-টাই বোঝার মতো। 4294967295-র octal লেখাটা এগারো অঙ্কের, ঘরের চেয়ে চওড়া, তাই ওই লাইনটা বাকি তিনটার চেয়ে এক অক্ষর লম্বা হয়ে বেরোয়। Width সবচেয়ে কম কতটুকু, সবচেয়ে বেশি কতটুকু না, আর যে program দশ অক্ষরে জোর করে আনতে চায় সেটা ভুল।
Zara-র sensor-কে কেবল একটা সীমার ভিতরে বিশ্বাস করা হয়। দুইটা তথ্য ছেপে দাও আর মানুষকে পড়তে দাও।
Input. এক লাইনে তিনটা পূর্ণসংখ্যা: সবচেয়ে কম যতটা চলে, সবচেয়ে বেশি যতটা চলে, আর পাঠটা।
Output. দুই লাইন, প্রতিটা 1 বা 0: সবচেয়ে কমের সমান বা বেশি, তারপর সবচেয়ে বেশির সমান বা কম।
Constraints. -1000000 <= সবচেয়ে কম <= সবচেয়ে বেশি <= 1000000। কোনো if না আর কোনো && না।
Sample. Input 1 100 50 দিলে 1 তারপর 1।
#include <stdio.h>
int main(void)
{
int low = 0;
int high = 0;
int reading = 0;
scanf("%d %d %d", &low, &high, &reading);
/* Two lines, each a comparison printed with %d. No if anywhere. */
return 0;
}
Run in Compiler
Hint 1
তুলনা একটা expression। মিললে তার মান 1, না মিললে 0।
Hint 2
তুলনাটা সোজা printf-র ভিতরে বসিয়ে দাও, যেখানে একটা মান আশা করা হয়, সাথে একটা %d।
Solution
দুইটা printf, প্রতিটায় একটা %d। প্রথমটা নেয় পাঠ আর সবচেয়ে কম মানের তুলনা, দ্বিতীয়টা সবচেয়ে বেশি মানের সাথে তুলনা। Module 2-র lesson 4 প্রমাণ করেছিল ওগুলোর প্রতিটাই একটা সংখ্যা, আর এর বেশি কিছু লাগে না।
দুইটা তুলনাতেই "বা সমান" আছে, কারণ ঠিক প্রান্তে বসা পাঠ সীমার ভিতরে ধরা হয়। দুইটা লুকানো test ঠিক ওই দুই ঘটনা, আর কড়া তুলনা দিয়ে লেখা program বাকি সব পাশ করে আর এই দুইটাই ফেল করে। দুইটা উত্তরকে এক করতে && লাগত, যেটা Module 4-র বিষয়, আর সেই কারণেই statement দুই লাইন চায়।
একটা পড়া আসলে কী করল সেটা জানাও: ও কী গোনা ফেরত দিল, আর তারপর variable-এ কী আছে।
Input. বড়জোর এক লাইন, তাতে একটা token, হয় একটা পূর্ণসংখ্যা নয় একটা শব্দ। ফাঁকাও হতে পারে।
Output. দুই লাইন: returned আর গোনাটা, তারপর value আর variable-টা।
Constraints. পূর্ণসংখ্যা -1000000 থেকে 1000000, শব্দ 1 থেকে 20 অক্ষরের, আর variable 0 থেকে শুরু।
Sample. Input twelve দিলে returned 0 তারপর value 0।
#include <stdio.h>
int main(void)
{
int amount = 0;
int read = scanf("%d", &amount);
/* Two lines. Print what scanf gave back, then what is in the box. */
return 0;
}
Run in Compiler
Hint 1
যে দুইটা মান লাগবে দুইটাই আগে থেকেই আছে। এই program-এ কিছুই হিসাব করা হয় না।
Hint 2
দুইটা printf, প্রতিটায় একটা করে %d, আর শব্দগুলো statement যেভাবে লিখেছে হুবহু সেভাবে।
Solution
returned শব্দটা, একটা ফাঁকা জায়গা আর read ছাপো, তারপর value শব্দটা, একটা ফাঁকা জায়গা আর amount। পুরো problem-টাই এই সত্যটা, যে দুইটা সংখ্যাই আগে থেকে আছে। যে program প্রথমটা ছুড়ে ফেলে, সে দুইটা মজার ঘটনার তফাত আর বুঝতে পারে না।
তিনটা লুকানো test কথাটা বলে দেয়। Input 0 দিলে দ্বিতীয় লাইন হয় value 0 আর প্রথম লাইন 1। Input twelve দিলে দ্বিতীয় লাইন একই থাকে আর প্রথম লাইন 0, কারণ পড়া ব্যর্থ হয়েছে আর declaration-র শূন্যটা অছোঁয়া থেকে গেছে। ফাঁকা input দেয় -1, মানে EOF, আর সেই একই অছোঁয়া শূন্য।
Amara-র দোকান একটা invoice roll ছাপে, আর auditor ওটা till-র নিজের copy-র সাথে অক্ষরে অক্ষরে মেলায়।
Input. তিন লাইন, প্রতিটায় একটা জিনিসের নাম, তার পরিমাণ আর পয়সায় প্রতি এককের দাম।
Output. আট লাইন: একটা header, তিনটা জিনিস, 27টা dash-র একটা দাগ, একটা subtotal সারি, একটা VAT সারি আর একটা total সারি। হুবহু format string-গুলো statement-এ আছে।
Constraints. নাম 1 থেকে 12 অক্ষরের। 0 <= পরিমাণ <= 9999, 0 <= প্রতি এককের দাম <= 99999। VAT হলো subtotal-র 15 শতাংশ, পূর্ণ পয়সায়, ভগ্নাংশ বাদ।
Sample. rice 12 4500, oil 3 12000 আর salt 7 250, এই তিনটা জিনিস দেয় subtotal 91750 আর VAT 13762।
#include <stdio.h>
int main(void)
{
const int VAT_PERCENT = 15;
const long long PERCENT_WHOLE = 100;
char first[16] = {0};
char second[16] = {0};
char third[16] = {0};
long long qty1 = 0;
long long qty2 = 0;
long long qty3 = 0;
long long price1 = 0;
long long price2 = 0;
long long price3 = 0;
scanf("%15s %lld %lld", first, &qty1, &price1);
scanf("%15s %lld %lld", second, &qty2, &price2);
scanf("%15s %lld %lld", third, &qty3, &price3);
/* Eight printf calls, in the widths the statement gives. */
return 0;
}
Run in Compiler
Hint 1
আট লাইনের ছয়টাই একটা format string ভাগ করে নেয়। আগে ওটাই লেখো আর তার তিনটা width ঠিক করো।
Hint 2
VAT সারির label-এ একটা সংখ্যা আছে, তাই ওটা %-12s ব্যবহার করতে পারে না। VAT %d%% আর টাকার কলাম পর্যন্ত পৌঁছানোর মতো চওড়া একটা ফাঁকা ঘর দিয়ে ওটা বানাও।
Solution
প্রতিটা জিনিসের লাইনের মোট বের করো, তারপর মোট পরিমাণ, subtotal আর VAT, সবই long long-এ। Header, তিনটা জিনিসের সারি, subtotal আর total সারি, ছয়টাই একই তিনটা width ব্যবহার করে: বাঁয়ে সাজানো বারো, তারপর পাঁচ, তারপর দশ। একটা ঠিক করলেই ছয়টা ঠিক।
VAT সারিটাই হাতে বানাতে হয়। VAT 15% সাত অক্ষরের আর বাকি সারিগুলো টাকার কলামের আগে সতেরো অক্ষর রাখে, তাই দশ চওড়া একটা ফাঁকা ঘর ফাঁকটুকু মিটিয়ে দেয়। Constraint-র একদম উপরে প্রতিটা ঘরই ঠিক ভরা, মানে subtotal সারিতে দুইটা সংখ্যা মাঝে ফাঁক ছাড়াই গায়ে গায়ে বসে, আর সেটা bug না, ঠিক output।
Bob-র import tool অন্য লোকের বানানো একটা file থেকে সংখ্যার জোড়া পড়ে, আর সেই লোকেরা মাঝেমাঝে অর্ধেক লিখে থেমে যায়।
Input. শূন্য থেকে ছয়টা পূর্ণসংখ্যা, মাঝে যত খুশি ফাঁকা জায়গা, যত খুশি লাইনে।
Output. তিন লাইন, প্রতি পড়ার জন্য একটা: scanf যা ফেরত দিল, তারপর দুইটা variable, এই ক্রমে আর ঠিক ওই মুহূর্তে।
Constraints. প্রতিটা পূর্ণসংখ্যা 0 থেকে 1000000। দুইটা variable-ই 0 থেকে শুরু। Input ফুরালে scanf EOF ফেরত দেয়, যেটা -1 হয়ে ছাপে।
Sample. Input 1 2 3 দিলে 2 1 2, তারপর 1 3 2, তারপর -1 3 2।
#include <stdio.h>
int main(void)
{
int a = 0;
int b = 0;
int first = scanf("%d %d", &a, &b);
/* Print first, a and b here, before the next read changes them. */
int second = scanf("%d %d", &a, &b);
/* Print second, a and b here. */
int third = scanf("%d %d", &a, &b);
/* Print third, a and b here. */
return 0;
}
Run in Compiler
Hint 1
তিনটা পড়া আর দুইটা বাক্স। প্রতিটা পড়া আগেরটার রেখে যাওয়া জিনিসের উপরেই লেখে।
Hint 2
Starter-র মন্তব্যগুলো ঠিক জায়গাতেই আছে। তিনটা পড়ার পরে বসানো একটা printf শেষ পড়ার মান তিনবার জানায়।
Solution
তিনটা printf, প্রতিটায় তিনটা %d, আর প্রতিটা নিজের scanf-র ঠিক পরেই বসা। ক্রমটাই পুরো problem। দুইটা বাক্সের মান সরতেই থাকে, আর পরে ছাপা একটা লাইন তার পাশের গোনার চেয়ে অন্য একটা মুহূর্তের কথা বলে।
মজার ঘটনাগুলো আসে অর্ধেক ভরা পড়া থেকে। Sample-এ দ্বিতীয় পড়াটা একটা সংখ্যা পায়, 3 প্রথম বাক্সে রাখে, তারপর input ফুরিয়ে যায় আর ও 1 ফেরত দেয়। দ্বিতীয় বাক্সে প্রথম পড়ার রেখে যাওয়া 2-ই থেকে যায়। Input একবার ফুরিয়ে গেলে পরের প্রতিটা পড়া EOF ফেরত দেয় আর কিছুই বদলায় না, তাই তৃতীয় লাইনটা দ্বিতীয় লাইনের জোড়াই আবার বলে।
যে প্রশ্নগুলো সবার মনে আসে
Starter-র
scanfলাইনটা কি বদলাতে পারি?পারো, আর তার কোনো কারণ নেই। ওটা আগে থেকেই ঠিক format, ampersand সহ, আর lesson 4-র ফাঁদগুলো আবিষ্কার করার জায়গা judge-র একটা problem না।
তিনটা problem
scanf-র ফেরত দেওয়া মান ছাপে কেন?কারণ "পড়া হলো কি" প্রশ্নের একমাত্র সৎ উত্তর ওই সংখ্যাটা। আর কারণ Module 5 ওটার উপর কাজ করার উপায় দেওয়ার আগে তুমি এটুকুই করতে পারো।
আমার output দেখতে ঠিক, তবু judge বলছে wrong answer।
যে লাইনটা প্রথম মেলেনি সেটার অক্ষর sample-র সাথে মিলিয়ে গোনো। প্রায় সবসময়ই ওটা ভরাটের একটা শূন্য, দুইটা specifier-র মাঝের একটা ফাঁকা জায়গা, বা সরাতে ভুলে যাওয়া একটা prompt।
শেষে একটা বাড়তি newline থাকলে কি সমস্যা?
না। Judge লাইনের শেষের আর output-র শেষের ফাঁকা জায়গা গ্রাহ্য করে না। মাঝখানে একটা newline না থাকা আলাদা কথা।
এদের কোনগুলো module test ব্যবহার করবে?
invoice-exactআরread-report, test-র note-এ নাম লেখা দুইটা। বাকি আটটা অনুশীলন আর সেগুলো খোলাই থাকে।
মূল কথা
- Output অংশটাই নির্দেশনা; গল্পটা কেবল বলে কোন problem ছিল।
- প্রতিটা starter-র
scanfলাইন যেমন দেওয়া আছে তেমনই ঠিক, আর তোমার কাজ শুরু তার পরে। - টাকা পূর্ণ পয়সায় গোনা হয় আর দশমিক বিন্দুটা
printfফিরিয়ে আনে। - Width সবচেয়ে কম কতটুকু, তাই সবচেয়ে বড় বৈধ input-র ঘর ভরে ফেলা বা উপচে যাওয়াই উদ্দেশ্য।
- হ্যাঁ বা না উত্তর মানে
%dদিয়ে ছাপা একটা তুলনা, কোথাও কোনোifনেই। - পরের পড়া চালু হওয়ার আগেই লাইনটা ছেপে ফেলো, নইলে পরে আসা মান জানাবে।
এরপর module test, তারপর Module 4, যেখানে এই দশটা problem যেসব operator এড়িয়ে চলেছে সেগুলো অবশেষে এসে হাজির হয়।
lesson ৬ শেষ
সব problem accepted হলেই lesson শেষ।
১০ টা problem-এর মধ্যে ০ টা accepted
পরেরটা: Module test: কনস্ট্যান্ট, ইনপুট আর আউটপুট