ভাঙলে বা মচকালে

ভাঙলে বা মচকালে
  আঘাতের স্থান ও পরিমাণ নিরূপণ করুন। হাতে বা পায়ে ফুলে গেলে সেখানে বরফ সেঁক দিন। ডাইক্লোফেনাক জেল হালকা করে লাগিয়ে দেওয়া যেতে পারে। তবে কোথাও কেটে গেলে ওই ক্ষতের ওপর সরাসরি এ রকম ক্রিম লাগাবেন না।
আক্রান্ত স্থান ম্যাসাজ করবেন না। আক্রান্ত স্থান বিশ্রামে রাখুন। ক্রেপ ব্যান্ডেজ দিয়ে মুড়িয়ে রাখুন।
তবে অতিরিক্ত ফুলে গেলে বা চামড়ার নিচে কালো হয়ে গেলে হাড়টি ভেঙেছে ধরে নেয়া যায়। সে ক্ষেত্রে চিকিৎসকের কাছে গিয়ে এক্স-রে করে নিশ্চিত হোন ও যথাযথ চিকিৎসা নিন
Share:

প্রোগ্রামিং ক্যারিয়ার

প্রোগ্রামিং ক্যারিয়ার
গণিত যেমন কেবল গণিতবিদেরাই ব্যবহার করেন না, বরং বিজ্ঞানের সব শাখায় রয়েছে এর ব্যবহার, তেমনই প্রোগ্রামিংও কিন্তু কেবল কম্পিউটার বিজ্ঞানী বা কম্পিউটার ইঞ্জিনিয়ারদের জন্য নয়। বিশ্ববিদ্যালয়ে পড়তে গেলে বিজ্ঞান ও প্রকৌশলের সব বিভাগের শিক্ষার্থীদের জন্য প্রোগ্রামিং জানাটা খুব গুরুত্বপূর্ণ।
পেশা হিসেবে প্রোগ্রামিংয়ের আলাদা একটি গুরুত্ব আছে আমাদের জন্য। যেহেতু বিভিন্ন ধরনের প্রতিযোগিতার মাধ্যমে নিজেকে মেলে ধরার অনেক সুযোগ এখানে রয়েছে ,তাই বাংলাদেশ থেকে লেখাপড়া করে সরাসরিই বিশ্বের নামকরা সফটওয়্যার নির্মাতা প্রতিষ্ঠান যেমন– গুগল, মাইক্রোসফট, ফেসবুক ইত্যাদিতে কাজ করার সুযোগ তৈরি হয়েছে। প্রতিবছরই বাংলাদেশ থেকে কয়েকজন প্রোগ্রামার নিজের মেধা ও জ্ঞানকে কাজে লাগিয়ে এই সুযোগের সদ্ব্যবহার করছেন। অনেক ক্ষেত্রেই ওইসব প্রতিষ্ঠানে কাজ করার জন্য আবেদন করার প্রয়োজন হয় না, তারা নিজে থেকেই বিভিন্ন দেশের সেরা প্রোগ্রামারদের খুঁজে বের করে।
বিশ্ববিখ্যাত সব প্রতিষ্ঠানে কাজ করা ছাড়াও প্রোগ্রামারদের জন্য আরেকটি সুবিধা হচ্ছে Telecommuting। অর্থাৎ কোনো অফিসে না গিয়ে কাজ করার সুযোগ। উন্নত বিশ্বের অনেক কোম্পানি তাদের নিজ দেশে প্রোগ্রামারদের দুষ্প্রাপ্যতার কারণে উন্নয়নশীল অর্থনীতির দেশের প্রোগ্রামারদের কাজের সুযোগ দেয়, আর সে ক্ষেত্রে নিজ দেশে বসেই কাজ করা যায়। কারণ ওই কোম্পানিগুলো জানে যে আমাদের মত দেশের অর্থনীতি উন্নয়নশীল হলেও প্রোগ্রামাররা মোটেও অদক্ষ নন, বরং বিশ্বমানের প্রোগ্রামার। বাংলাদেশের বেশকিছু প্রোগ্রামার এখন বাংলাদেশে বসেই ইন্টারনেটের মাধ্যমে কাজ করছেন আমেরিকা, কানাডা ও ইউরোপের বিভিন্ন দেশের সফটওয়্যার কোম্পানিতে।
আরেকটি মজার ব্যাপার হচ্ছে, কেউ যদি ধরাবাঁধা চাকরি করতে না চায় তবে তার জন্য ফ্রিল্যান্স প্রোগ্রামিংয়ের সুযোগ রয়েছে। ইন্টারনেটে অনেক ওয়েবসাইট আছে যেখানে ছোট-মাঝারি-বড় বিভিন্ন ধরনের সফটওয়্যারের প্রজেক্ট থাকে যেগুলোতে বিড (bid) করে কাজ করা যায়। বাংলাদেশে এখন শত শত প্রোগ্রামার ফ্রিল্যান্স প্রোগ্রামিংয়ের সঙ্গে জড়িত। এর জন্য কেবল কম্পিউটার ও ইন্টারনেট সংযোগ থাকলেই চলবে। ফ্রিল্যান্স কাজ করার জন্য বিপুল ধৈর্যের প্রয়োজন। আর ইংরেজি ভাষায় যোগাযোগের দক্ষতা থাকতে হয়। তবে ব্যক্তিগতভাবে আমি মনে করি, ছাত্রাবস্থায় এ ধরনের কাজ না করাই ভালো। কারণ ছাত্রজীবনে লেখাপড়া করার ও মৌলিক বিষয়গুলো আয়ত্ত্ব করার যে সময় ও সুযোগ মেলে, জীবনের পরবর্তী পর্যায়ে কখনোই সেই সুযোগ পাওয়া যায় না। তাই তোমাদের প্রতি আমার পরামর্শ থাকবে যে ছাত্রজীবনে অর্থ উপার্জনের দিকে মনোযোগ না দিয়ে প্রচুর লেখাপড়া এবং সঙ্গে সঙ্গে নানা ধরনের সামাজিক ও সাংস্কৃতিক কর্মকাণ্ডে জড়িত থাকার চেষ্টা করবে, যেগুলো তোমার ভালো লাগে।
সব শেষ কথা হচ্ছে, প্রোগ্রামিং এমন একটি কাজ যেখানে সব সময়ই তোমার নিজেকে উন্নত করার সুযোগ আছে। তাই লেখাপড়া করার মানসিকতা থাকতে হবে, পড়তে হবে নানা বইপত্র, ঘাঁটতে হবে ইন্টারনেট। নিজে কোনো সমস্যায় পড়লে প্রথমেই ইন্টারনেট ঘেঁটে দেখবে যে সমস্যাটির সমাধান ইতিমধ্যে কেউ করে রেখেছে কি না। বিভিন্ন ফোরাম ও ব্লগে সাধারণত প্রোগ্রামাররা কিছু কমন সমস্যার সমাধান দিয়ে রাখে। তবে প্রোগ্রামিং শেখার সময় কিন্তু সমাধানের জন্য ইন্টারনেট ঘাঁটবে না, নিজে চেষ্টা করবে
Share:

প্রোগ্রামিং বই ও ওয়েবসাইটের তালিকা

প্রোগ্রামিং  ওয়েবসাইটের তালিকা
তুমি যদি ইতিমধ্যে এই বইটি পড়ে ফেলো এবং এবারে ভালোভাবে সি শিখতে চাও, তবে Herbert Schildt-এর Teach Yourself C বইটি পড়তে পারো। আবার Brian Kernighan ও Dennis Ritchie-এর লেখা The C Programming Language বইটিও পড়তে পারো। লেখকদের একজন, Dennis Ritchie, সি ল্যাঙ্গুয়েজ ডিজাইন করেছেন। আর কেউ যদি তোমার কাছে জানতে চায় শুরুতে সি শিখতে হলে কোন ইংরেজি বইটি ভালো তবে Stephen G. Kochan-এর Programming in C বইটির কথা বলে দেবে। এটি সি শেখার জন্য চমৎকার ও সহজ একটি বই। Schaums Outlines সিরিজের Programming with C বইটিও ভালো। বইতে প্রচুর উদাহরণ আর অনুশীলনী আছে।
সি শেখার পরে তুমি সি প্লাস প্লাস বা জাভা শিখতে পারো। সি প্লাস প্লাস শেখার জন্য ভালো বই হচ্ছে Teach Yourself C++ (লেখক: Herbert Schildt) আর জাভার জন্য Java How to Program (লেখক: Paul Deitel and Harvey Deitel)। তারপর অন্য ল্যাঙ্গুয়েজ শিখতে গেলে আর বই কেনার দরকার নেই। ইন্টারনেটে প্রচুর টিউটোরিয়াল আছে। সেগুলো পড়ে শিখে ফেলবে। সি এবং পাইথনের জন্য চমৎকার দুটি বই আছে অনলাইনে - http://learnpythonthehardway.org/book/ http://c.learncodethehardway.org/book/
তুমি যদি কম্পিউটার বিজ্ঞানে পড়তে চাও, কিংবা প্রোগ্রামিং কন্টেস্টে ভালো করতে চাও, তাহলে তোমার Discrete Mathematics ভালো করে শিখতে হবে। এর জন্য Kenneth H. Rosen-এর Discrete Mathematics বইটি খুব ভালো। আগাগোড়া পড়ে ফেলবে। সঙ্গে সঙ্গে অনুশীলনীর সমস্যাগুলো সমাধানের চেষ্টা করবে। Discrete Mathematics শেখার পরে শিখতে হবে অ্যালগরিদম। অ্যালগরিদম শেখার শুরু আছে কিন্তু শেষ নেই। আর শুরু করার জন্য তোমরা পড়তে পারো Introduction to Algorithms (লেখক: Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest and Clifford Stein) এটি অ্যালগরিদমের মৌলিক বিষয়গুলো শেখার জন্য আমার দেখা সবচেয়ে ভালো বই।
প্রোগ্রামিং প্রতিযোগিতার জন্য কিছু লিংক:
    http://projecteuler.net/ এখানে অনেক মজার সমস্যা আছে যেগুলোর বেশিরভাগই প্রোগ্রাম লিখে সমাধান করতে হয়। এখানে প্রোগ্রাম জমা দেওয়া লাগে না, কেবল প্রোগ্রাম দিয়ে বের করা উত্তরটা জমা দিতে হয়।     http://www.spoj.pl/ এখানেও অনেক ভালো সমস্যা আছে। সমাধান করে প্রোগ্রাম জমা দিলে প্রোগ্রাম সঠিক হয়েছে কি না তা জানা যায়। এই ওয়েবসাইটের একটি বৈশিষ্ট্য হচ্ছে সি, সি প্লাস প্লাস, জাভা, পার্ল, পাইথন, রুবি, পিএইচপি ইত্যাদি ব্যবহার করে প্রোগ্রাম লেখা যায়।     http://uva.onlinejudge.org/ এই সাইটে নিয়মিত অনলাইন প্রোগ্রামিং প্রতিযোগিতার আয়োজন করা হয়। এ ছাড়াও অনুশীলনের জন্য প্রচুর সমস্যা দেওয়া আছে। নতুন প্রোগ্রামারদের জন্য এটি বেশ ভালো জায়গা।     http://ace.delos.com/usacogate এটি যদিও আমেরিকার ইনফরমেটিক্স অলিম্পিয়াড ট্রেনিং প্রোগ্রাম, কিন্তু সাইটে যেকোনো দেশের প্রোগ্রামাররাই রেজিস্ট্রেশন করে অনুশীলন করতে পারে। তোমরা যারা প্রোগ্রামিং প্রতিযোগিতায় ভালো করতে চাও, তাদের অবশ্যই এখানে অনুশীলন করা উচিত।     http://www.topcoder.com/tc এখানেও নিয়মিত অনলাইন প্রোগ্রামিং প্রতিযোগিতা অনুষ্ঠিত হয়। এখানে ভালো ফলাফল করলে আবার টাকাও দেয় (কী আনন্দ!)। এ ছাড়া এখানে অনেক ভালো টিউটোরিয়াল ও আর্টিকেল আছে। এটি অভিজ্ঞ প্রোগ্রামারদের জন্য বেশ ভালো একটি সাইট।     http://codeforces.com এই সাইটে নিয়মিত বিভিন্ন ধরনের প্রোগ্রামিং কন্টেস্ট হয়। অভিজ্ঞ প্রোগ্রামারদের জন্য ভালো।      http://www.codechef.com এটিও প্রোগ্রামিং প্রতিযোগিতার জন্য একটি ভালো ওয়েবসাইট এবং অভিজ্ঞ প্রোগ্রামারদের জন্য।     http://ioinformatics.org আন্তর্জাতিক ইনফরমেটিক্স অলিম্পিয়াডের অফিসিয়াল ওয়েবসাইট।     http://cm.baylor.edu/welcome.icpc এসিএম আইসিপিসির অফিসিয়াল ওয়েবসাইট।
প্রোগ্রামিং ছাড়াও বিজ্ঞান ও গণিতের নানা বিষয়ের জন্য এই ফোরামে অংশগ্রহণ করতে পারো: http://matholympiad.org.bd/forum/।
বাংলা ভাষায় প্রোগ্রামিং সংক্রান্ত কোর্স অনলাইনে করার ব্যবস্থা করছে দ্বিমিক কম্পিউটিং স্কুল। সেখানে প্রোগ্রামিংয়ে হাতেখড়ি, ওয়েব কনসেপ্টস ও ডিসক্রিট ম্যাথের উপর কোর্স রয়েছে।
আর সবচেয়ে গুরুত্বপূর্ণ ওয়েবসাইট হচ্ছে www.google.com। এটি আসলে একটি সার্চ ইঞ্জিন। যখনই কোন কিছু জানতে ইচ্ছা করবে, google-এ সার্চ করলে তুমি সেই বিষয়ের নানা তথ্যসমৃদ্ধ ওয়েবসাইটের লিংক পেয়ে যাবে
Share:

প্রোগ্রামিং প্রতিযোগিতা

প্রোগ্রামিং প্রতিযোগিতা
প্রোগ্রামিং প্রতিযোগিতা হচ্ছে প্রোগ্রামারদের মধ্যে লড়াই। এর মানে কিন্তু এই নয় যে প্রোগ্রামাররা একে অপরের সঙ্গে মারামারি করবে আর শেষ পর্যন্ত যে টিকে থাকবে সে-ই বিজয়ী। আসলে প্রোগ্রামিং প্রতিযোগিতা হচ্ছে একটি পরীক্ষার মতো যেখানে প্রত্যেককে একটি নির্দিষ্ট সময়ে নির্দিষ্টসংখ্যক প্রোগ্রামিং সমস্যার সমাধান করতে দেওয়া হবে। যে সবচেয়ে বেশি সমস্যার নির্ভুল সমাধান করবে সে বিজয়ী হবে। আর দুজন যদি সমানসংখ্যক সমস্যার সমাধান করে, তবে তাদের মধ্যে যে কম সময়ে করেছে সে বিজয়ী। তবে স্কুল-কলেজের পরীক্ষার সঙ্গে এর পার্থক্য হচ্ছে, এখানে বই থেকে সরাসরি প্রশ্ন করা হয় না। তাই মুখস্থ করার কোনো সুযোগ নেই। বিচারকেরা অনেক সময় নিয়ে প্রোগ্রামিং প্রতিযোগিতার সমস্যা তৈরি করেন। এর মধ্যে সহজ সমস্যাও থাকে আবার খুব কঠিন সমস্যাও থাকে।
স্কুল-কলেজের ছাত্রছাত্রীদের জন্য সবচেয়ে বড় প্রতিযোগিতা হচ্ছে আইওআই (IOI– International Olympiad in Informatics)। 1989 সাল থেকে প্রতিবছর এ প্রতিযোগিতা অনুষ্ঠিত হচ্ছে। একেক বছর একেক দেশে প্রতিযোগিতা অনুষ্ঠিত হয়। বিগত চার বছর যাবৎ বাংলাদেশ এ প্রতিযোগিতায় অংশগ্রহণ করে আসছে। এখন পর্যন্ত আমাদের সেরা অর্জন হচ্ছে 2009 সালে আবিরুল ইসলামের রৌপ্য পদক (সিলভার মেডেল)। IOIতে অংশগ্রহণ করার জন্য বাংলাদেশ দল গঠনের কাজটি করা হয় দুই ধাপে। প্রথমে বিভাগীয় ইনফরমেটিক্স অলিম্পিয়াড। তারপর বিভাগীয় পর্যায়ের বিজয়ীদের নিয়ে জাতীয় ইনফরমেটিক্স অলিম্পিয়াড অনুষ্ঠিত হয়। জাতীয় অলিম্পিয়াডের বিজয়ীদের মধ্য থেকেই দলের সদস্য বাছাই করা হয়।
বিশ্ববিদ্যালয় পর্যায়ের ছাত্রছাত্রীদের জন্য সবচেয়ে বড় প্রোগ্রামিং প্রতিযোগিতা হচ্ছে এসিএম আইসিপিসি (ACM ICPC– ACM International Collegiate Programming Contest)। এর জন্য দল বাছাই অনেকটা বিশ্বকাপ ফুটবলের মতো হয়। প্রতি মহাদেশ থেকে প্রতিযোগিতার মাধ্যমে দল নির্বাচন করা হয়। একটি দলে তিনজন সদস্য এবং একজন প্রশিক্ষক থাকেন। মজার ব্যাপার হচ্ছে দলের সদস্যদের কিন্তু কম্পিউটার বিজ্ঞানের শিক্ষার্থী হতে হবে, এমন কোনো কথা নেই। যেকোনো বিভাগের শিক্ষার্থী এই প্রতিযোগিতায় অংশগ্রহণ করতে পারে। বাংলাদেশের প্রতিযোগিরা ঢাকায় ICPC Regional Contest-এ অংশগ্রহণ করে। এছাড়া ভারত ও আশেপাশের দেশের ICPC Regional Contest-এও বাংলাদেশের প্রতিযোগীদের অংশগ্রহণের সুযোগ রয়েছে এবং প্রায়ই আমাদের দেশের কয়েকটি দল ওইসব প্রতিযোগিতায় অংশগ্রহণ করে। ICPC Regional Contest-এ বিজয়ী দলগুলো সুযোগ পায় চূড়ান্ত পর্বে (ICPC World Finals) অংশগ্রহণ করার। 1998 সালের পর থেকে প্রতি বছরই বাংলাদেশ থেকে কমপক্ষে একটি দল চূড়ান্ত পর্বে অংশগ্রহণের যোগ্যতা লাভ করে যা আমাদের দেশের প্রোগ্রামারদের কৃতিত্বের পরিচয় বহন করে। তোমরা এ বিষয়ে উইকিপিডিয়াতে আরও তথ্য পাবে এই লিংকে: http://en.wikipedia.org/wiki/ACM_ICPC_Dhaka_Site।
এছাড়া ইন্টারনেটে অনুষ্ঠিত হয় আরও নানা ধরনের প্রোগ্রামিং প্রতিযোগিতা যেখানে স্কুল-কলেজ-বিশ্ববিদ্যালয়ের ছাত্র, শিক্ষক ও পেশাজীবীরা অংশ্রগ্রহণ করতে পারেন। এদের মধ্যে গুরুত্বপূর্ণ তিনটি হচ্ছে Google Code Jam (http://code.google.com/codejam), Topcoder (http://www.topcoder.com/tc) এবং Codechef (http://www.codechef.com/)। এই প্রতিযোগিতাগুলো অত্যন্ত কঠিন, তাই এতে অংশগ্রহণের জন্য পর্যাপ্ত দক্ষতা থাকতে হবে। তবে এসব প্রতিযোগিতায় কিন্তু বাংলাদেশের প্রোগ্রামাররা বেশ ভালো অবস্থানে রয়েছে।
প্রোগ্রামিং প্রতিযোগিতায় ভালো করতে হলে প্রোগ্রামিংয়ে দক্ষতার পাশাপাশি অ্যালগরিদম ও গণিতে বিশেষভাবে দক্ষ হতে হয়। জ্যামিতি, কম্বিনেটরিক্স, সংখ্যাতত্ত্ব ইত্যাদির যথেষ্ট জ্ঞানের পাশাপাশি সমস্যা সমাধানের দক্ষতা অর্জন করতে হয়। এজন্য লেখাপড়ার পাশাপাশি নিয়মিত প্রোগ্রামিং সমস্যা সমাধানের কোনো বিকল্প নেই। আর বিভিন্ন ওয়েবসাইটে নিয়মিত প্রোগ্রামিং প্রতিযোগিতার আয়োজন করা হয় যেখানে তুমি অংশগ্রহণ করতে পারো ইন্টারনেটের মাধ্যমে
Share:

বিষাক্ত পোকার কামড়ের

বিষাক্ত পোকার কামড়ের
 বিষাক্ত পোকার কামড়ের স্থানে বরফ দেওয়া দেতে পারে। প্রয়োজনে সাবান পানি দিয়ে ধুয়ে ফেলুন এবং ক্ষত স্থানে এন্টিসেপটিক লোশন প্রয়োগ করুন। সাপের কামড়ের ক্ষেত্রে দাঁতের দাগ দেখে চিনতে চেষ্টা করতে হবে, সাপটি বিষাক্ত কি না। বিষধর সাপের ক্ষেত্রে দুই সারি দাঁতের দাগের বাইরে আরো দুটি দাগ দেখা যাবে। সাপের কামড়ের কয়েক ইঞ্চি উপরে কাপড় বা রাবার ব্যান্ড দিয়ে বেঁধে দিতে হবে যাতে রক্ত চলাচল কমে যায়। প্রয়োজনে সাপের কামড়ের স্থানে কেটে নিয়ে রক্ত শুষে ফেলতে হবে_ তবে পদ্ধতিটি অবশ্যই শিখে নিতে হবে
Share:

পুড়ে যাওয়া রোগীর

পুড়ে যাওয়া রোগীর
 প্রাথমিক চিকিৎসা পুড়ে যাওয়া সাধারণত তিন ধরনের
১ম ডিগ্রী: তাপ লেগে চামড়া লাল হয়ে যায়। কোনো ফোস্কা পড়ে না। ২য় ডিগ্রী: চামড়া পুড়ে ফোস্কা পড়ে। ৩য় ডিগ্রী: পুড়ে যাওয়ার গভীরতা চামড়া ভেদ করে মাংস পর্যন্ত বিস্তৃত হয়। পুড়ে যাওয়া প্রাথমিক চিকিৎসা রোগীকে দ্রুত আগুনের উৎস থেকে সরিয়ে আনতে হবে। * পরনের কাপড়ে আগুন লাগলে মোটা কাপড় বা কম্বল দিয়ে রোগীকে জড়িয়ে ধরতে হবে। এবং মাটিতে শুয়ে গড়াতে হবে। এতে আগুন নিভে যাবে।
* শরীরের যে অঙ্গ পুড়ছে সেখানে পানি ঢালতে হবে। ;
* ১ম ডিগ্রী পোড়ার ক্ষেত্রে শুধুমাত্র পানি ঢাললেই হবে, আর কোনো চিকিৎসার প্রয়োজন নেই। পানি ঢালতে হবে ১৫ মিনিট থেকে ২০ মিনিট।
* ২য় ডিগ্রী পোড়ার ক্ষেত্রে লম্বা সময় ধরে পানি ঢালতে হবে, ১-২ ঘণ্টা পর্যন্ত। এক্ষেত্রে ফোস্কা গরানোর দরকার নেই। প্রাথমিক চিকিৎসার পর চিকিৎসকের পরামর্শ নেওয়া উচিত।
* ৩য় ডিগ্রী পোড়ার ক্ষেত্রে যত দ্রুত সম্ভব রোগীকে হাসপাতালে নেওয়া উচিত। হাপাতালে নেওয়ার পূর্বে পোড়া স্থানে পানি ঢালতে হবে।
Share:

প্রোগ্রামিং শেষের শুরু

প্রোগ্রামিং  শেষের শুরু
আমরা বইয়ের শেষ অধ্যায়ে চলে এসেছি। তোমরা যদি আগের অধ্যায়গুলো ঠিকমতো পড়ে থাকো, উদাহরণগুলো নিজে নিজে কম্পিউটারে চালিয়ে দেখে থাকো এবং যখনই আমি তোমাদেরকে কোনো প্রোগ্রাম নিজে লিখতে বলেছি, সেগুলো নিজে লিখার চেষ্টা করে থাকো, তাহলে তোমাকে অভিনন্দন! তুমি প্রোগ্রামিং শেখার জন্য প্রস্তুত হয়ে গেছ। যদি বলতে পারতাম তুমি প্রোগ্রামিং শিখে ফেলেছ তবে তোমাদেরও ভালো লাগত, আমারও ভালো লাগত, কিন্তু মিথ্যা কথা বলে কী লাভ?
প্রোগ্রামিং হচ্ছে চর্চার বিষয়। মুখস্থ করে পরীক্ষায় অনেক ভালো রেজাল্ট করা যায়, এমনকি কলেজ-বিশ্ববিদ্যালয়ে প্রোগ্রামিং পরীক্ষাতেও মুখস্থ করে অনেকেই বেশ ভালো নম্বর পায়। তবে এই ভালো নম্বর পাওয়ার সঙ্গে ভালো প্রোগ্রামার হওয়ার আসলে কোন সম্পর্ক নেই। প্রোগ্রামিং হচ্ছে একধরনের দক্ষতা (skill) এবং কেবল নিয়মিত অনুশীলনের মাধ্যমেই এই দক্ষতা অর্জন করা সম্ভব। এর জন্য ভালো ছাত্র হওয়ার দরকার নেই, জিনিয়াস হওয়ারও কোনো দরকার নেই। দরকার হচ্ছে প্রোগ্রামিংকে ভালোবাসা। যখন তুমি প্রোগ্রামিং করতে বসলে খাওয়াদাওয়ার কথা ভুলে যাবে, রাতে কোনো প্রোগ্রামিং সমস্যা নিয়ে কাজ শুরু করলে আর কিছুক্ষণ পরে দেখবে বাইরে ভোরের আলো ফুটছে, কিংবা ভুলে বাথরুমের স্যান্ডেল পরে ক্লাসে চলে যাবে, তখন বুঝবে যে তুমি প্রোগ্রামার হয়ে যাচ্ছ।
এখন তোমার উচিত হবে বইটি আরেকবার পড়া এবং সঙ্গে সঙ্গে প্রোগ্রামগুলো আবার করা। তারপর তোমরা আরও বেশি সি শিখতে চাইলে সি-এর কোন বই পড়তে পারো। তোমরা যদি প্রোগ্রামিং কন্টেস্টের ব্যাপারে উৎসাহী হও তবে সি প্লাস প্লাস (C++) শেখা শুরু করে দিতে পারো কোন বই থেকে। আবার জাভা (Java), সি শার্প (C#), পিএইচপি (PHP) কিংবা পাইথন (Python) শিখতে পারো। কোনোটি শিখতেই তেমন ঝামেলা পোহাতে হবে না কারণ তুমি প্রোগ্রামিংয়ের মৌলিক জিনিসগুলো এতক্ষণে আয়ত্বে এনে ফেলেছ। বই ও ওয়েবসাইটের তালিকা আমি পরিশিষ্ট অংশে লিখেছি।
একজন দক্ষ প্রোগ্রামার হতে গেলে যে জিনিসগুলো লাগবে তা হচ্ছে– ১) এক বা একাধিক প্রোগ্রামিং ল্যাঙ্গুয়েজে ভালো দখল, ২) ভালো একটি IDE ব্যবহারের দক্ষতা, ৩) প্রোগ্রামিংয়ের মৌলিক বিষয়গুলো সম্পর্কে স্বচ্ছ ধারনা, ৪) গণিত ও যুক্তিতে দক্ষতা, ৫) অবজেক্ট ওরিয়েনটেড প্রোগ্রামিংয়ে (OOP– Object Oriented Programming) দক্ষতা, ৬) ডাটা স্ট্রাকচার ও অ্যালগরিদমের মৌলিক জ্ঞান ও তা প্রয়োগের ক্ষমতা, ৭) যোগাযোগে দক্ষতা (Communication Skills), ৮) ইন্টারনেট ঘেঁটে অল্প সময়ে কোনো সমস্যার সমাধান বের করা বা দ্রুত কোন নতুন বিষয় শিখে নেওয়ার দক্ষতা, ৯) একটি সমস্যার পিছনে লেগে থাকার মানসিকতা, ১০) প্রোগ্রামিংয়ের প্রতি ভালোবাসা।
তোমাদের প্রোগ্রামিং জীবন আনন্দময় হোক, তোমাদের নিজের জীবন আনন্দময় হোক, তোমাদের কারণে তোমাদের আশেপাশের মানুষদের জীবন আনন্দময় হোক। সবাইকে শুভেচ্ছা
Share:

কিছু প্রোগ্রামিং সমস্যা

প্রোগ্রামিং সমস্যা
এই অ‌ধ্যায়ে আমরা কয়েকটি সহজ সমস্যা দেখব ও সমাধানের চেষ্টা করব।
আমাদের প্রথম সমস্যা হচ্ছে, বিভিন্ন ধরনের আকৃতি তৈরি করা। নিচের ছবিগুলো দেখো।
তোমাদের চারটি প্রোগ্রাম লিখতে হবে এই চার ধরনের আকৃতি তৈরি করার জন্য। কেবল printf ফাংশন ব্যবহার করলেই হবে না, লুপ ব্যবহার করতে হবে। তাহলে লুপ বা নেস্টেড লুপ, এবং 'c' ও ' ' (স্পেস ক্যারেক্টার) প্রিন্ট করে তোমরা প্রোগ্রামগুলো লিখে ফেলতে পারো। আরও খেলাধুলা করার ইচ্ছা হলে আরও নানান রকম আকৃতি তৈরির চেষ্টা করতে পার।
প্যালিন্ড্রোম (palindrome) কী জিনিস, তোমরা জান? কোনো শব্দকে উল্টাভাবে (মানে শেষ থেকে শুরু) লিখলে যদি সেটি আর নতুন শব্দটি একই রকম হয় তবে সেটি একটি প্যালিন্ড্রোম। যেমন: madam। এটিকে শেষ থেকে শুরু পর্যন্ত লিখলেও madam হবে। এখন একটি প্রোগ্রাম লিখব যেটিতে কোনো শব্দ ইনপুট দিলে সেটি প্যালিন্ড্রোম কি না বলে দেবে।
এজন্য আমরা কী করতে পারি? প্রথমে শব্দটি স্ট্রিং হিসেবে একটি অ্যারেতে ইনপুট নেব। তারপর আরেকটি অ্যারেতে সেটি উল্টাভাবে রাখব। তারপর যদি দুটি একই স্ট্রিং হয়, তবে সেটি প্যালিন্ড্রোম। তাহলে প্রোগ্রামটি লিখে ফেলি:
#include <stdio.h> #include <string.h> int main() { char word[80], reverse_word[80]; int i, j, len; scanf("%s", word); len = strlen(word); for(i = 0, j = len - 1; i < len; i++, j--) { reverse_word[i] = word[j]; } reverse_word[i] = '\0'; printf("%s\n", reverse_word); if (0 == strcmp(word, reverse_word)) { printf("%s is a palindrome.\n", word); } else { printf("%s is not a palindrome.\n", word); } return 0; } প্রোগ্রাম: ১৩.১
কী মজা! আমি প্রোগ্রামটি লিখে দিলাম। তবে আমি এখানে বেশ কিছু বোকামি করেছি, যার মধ্যে অন্যতম হচ্ছে একটি অতিরিক্ত অ্যারে ব্যবহার করা। সুতরাং তোমাদের এখন প্রোগ্রামটি এমনভাবে লিখতে হবে, যাতে কেবল একটি অ্যারে ব্যবহার করেই কাজ হয়। আর তখন strcmp ফাংশনটিরও দরকার হবে না। প্রোগ্রামটি লিখতে সময় বেশি লাগতে পারে, লাগুক, অসুবিধা নেই। তবে লিখতে হবে ঠিকঠাক, এটিই হলো কথা।
তোমরা তো ফ্যাক্টরিয়াল (factorial) জিনিসটির সঙ্গে পরিচিত? এটি একটি গাণিতিক অপারেশন যা কোনো ধনাত্মক পূর্ণসংখ্যার ক্ষেত্রে ব্যবহার করা যায়। n একটি ধনাত্মক পূর্ণ সংখ্যা হলে-এর ফ্যাক্টরিয়ালকে প্রকাশ করা হয় n! দিয়ে এবং n! = n * (n – 1) * (n – 2) * … * 3 * 2 * 1। যেমন 4! = 4 * 3 * 2 * 1 = 24। আবার 6! = 6 * 5 * 4 * 3 * 2 * 1 = 720। 1! = 1। 0! = 1 (0-এর ক্ষেত্রে ব্যতিক্রমটি লক্ষ করো, কিছু বিশেষ সুবিধার জন্য 0-এর ফ্যাক্টরিয়ালের মান 1 ধরা হয়)। এখন তোমরা কোনো ধনাত্মক পূর্ণসংখ্যার ফ্যাক্টরিয়াল বের করার প্রোগ্রামটি লিখে ফেলো। সহজ প্রোগ্রাম, একটি লুপ ব্যবহার করেই করা যায়। এখন বিভিন্ন সংখ্যা দিয়ে প্রোগ্রামটি টেস্ট করে দেখো ফ্যাক্টরিয়াল ঠিকঠাক বের করতে পারে কি না। প্রোগ্রামে তুমি যদি ডাটা টাইপ int ব্যবহার করে থাক তবে 12-এর চেয়ে বড় কোনো পূর্ণ সংখ্যার ফ্যাক্টরিয়ালের মান ঠিকমতো দেখাবে না (ক্যালকুলেটরে করে মিলিয়ে দেখতে পারো)। কারণ হচ্ছে 12-এর চেয়ে বড় কোনো পূর্ণ সংখ্যার জন্য সেই সংখ্যার ফ্যাক্টরিয়ালের মান রেঞ্জের বাইরে চলে যায়।
এখন তোমাদের একটি মজার সমস্যা সমাধান করতে হবে। কোনো পূর্ণসংখ্যা n (যেখানে 1 < n < 100, মানে n-এর মান 2 থেকে 99 পর্যন্ত হতে পারে)-এর ফ্যাক্টরিয়ালকে মৌলিক সংখ্যার গুণফল হিসেবে প্রকাশ করলে কোন মৌলিক সংখ্যা কতবার আছে সেটি বের করতে হবে। যেমন, আমরা জানি, 5! = 120 = 2 * 2 * 2 * 3 * 5। এখানে 2 আছে 3 বার, 3 আছে 1 বার আর 5 আছে 1 বার। তাই ইনপুট 5 হলে আউটপুট হবে: 5! = (2, 3), (3, 1), (5, 1)। তোমরা কি একটি ব্যাপার বুঝতে পারছ যে শুরুতে n-এর ফ্যাক্টরিয়ালের মান বের করে তারপর মৌলিক উৎপাদকে ভাঙতে গেলে একটি ঝামেলা হয়ে যাবে? কারণ n-এর মান সর্বোচ্চ হতে পারে 99 আর ইন্টিজারে তো 12-এর চেয়ে বড় কোনো সংখ্যার ফ্যাক্টরিয়ালের মান রাখা যায় না। আসলে এই প্রোগ্রামের জন্য n!-এর মান বের করার কোনো দরকার নেই। শুধু একটু গাণিতিক যুক্তি-বুদ্ধি খাটাও। আর 2 থেকে 99 পর্যন্ত মৌলিক সংখ্যাগুলো একটি অ্যারেতে রেখে নাও। প্রোগ্রামটি ঠিকভাবে করতে তোমাদের অনেকেরই দু-তিন দিন সময় লেগে যেতে পারে, এতে হতাশ হওয়ার কিছু নেই।
এখন আমরা একটি প্রোগ্রাম লিখব। যার উদ্দেশ্য হবে কোনো অ্যারেতে কিছু সংখ্যা থাকলে সেগুলোকে ছোট থেকে বড় ক্রমে সাজানো। যেমন, কোনো অ্যারে যদি এমন হয়: int ara[] = {3, 1, 5, 2, 4}, তবে আমাদের প্রোগ্রাম সেই অ্যারের সংখ্যাগুলো এমনভাবে সাজাবে, যাতে ara[] = {1, 2, 3, 4, 5} হয়।
প্রোগ্রামটি একটু পরে লিখব, তার আগে ঠিক করে নেই যে সেটি কীভাবে কাজ করবে। তোমার কাছে পাঁচটি সংখ্যা আছে: 3, 1, 5, 2, 4। ছোট থেকে বড় ক্রমে সাজাতে হবে। তুমি প্রথমে কী করবে? প্রথমে সবচেয়ে ছোট সংখ্যাটি খুঁজে বের করে তাকে শুরুতে লিখবে: 1। তখন বাকি থাকে চারটি সংখ্যা: 3, 5, 2, 4। এখন এই চারটির মধ্যে সবচেয়ে ছোট সংখ্যাটি 1-এর পরে লিখবে: 1, 2। বাকি রইল 3, 5, 4। এদের মধ্যে সবচেয়ে ছোট 3। তাই তুমি লিখবে : 1, 2, 3। এখন বাকি 5, 4। এই দুটি সংখ্যার মধ্যে সবচেয়ে ছোট 4। সেটি তুমি 3-এর পরে লিখবে: 1, 2, 3, 4। এখন বাকি একটি সংখ্যা, 5। সেটি তুমি 4-এর পরে লিখবে। 1, 2, 3, 4, 5। তোমার সাজানোর কাজ হয়ে গেল। একে সর্টিং (sorting) বলে। বিভিন্ন উপায়ে এটি করা যায়। তবে আমরা একটি সহজ-সরল উপায়ে করলাম।
আমরা যেভাবে কাজটি করেছি, সেটি উইকিপিডিয়াতে চমৎকার একটা অ্যানিমেশনের সাহায্যে দেখানো হয়েছে। অ্যানিমেশনটি একবার দেখলে বোঝা কঠিন, তাই আমার পরামর্শ হচ্ছে কমপক্ষে চার-পাঁচবার এটি দেখো।
এখন প্রোগ্রামটি লিখব কীভাবে?
প্রথমে একটি অ্যারেতে সংখ্যাগুলো রাখো: int ara1[] = {3, 1, 5, 2, 4}; এখন আরেকটি অ্যারে নাও:

int ara2[5]; অ্যারেটি এখনো খালি। তাই একটি ভেরিয়েবলে ইনডেক্স 0 লিখে রাখো। int index_2 = 0; এখন একটি একটি করে ara2তে সংখ্যাগুলো রাখতে হবে। তার জন্য একটি লুপ দরকার। for(index_2 = 0; index_2 < 5; index_2++) // মানে 0 থেকে 4 পর্যন্ত প্রতিটি ঘরে আমরা সংখ্যা বসাব। এই লুপের ভেতরে আরেকটি লুপ দরকার যেটি দিয়ে আমরা ara1-এর সবচেয়ে ছোট সংখ্যা খুঁজে বের করব। minimum = 100000; // এমন একটি বড় সংখ্যা অ্যাসাইন করলাম যেটি ara1-এর যেকোনো সংখ্যার চেয়ে বড়। for (i = 0; i < 5; i++) {  if (ara1[i] < minimum) {   minimum = ara1[i];  } } এখন ara1-এর ক্ষুদ্রতম সংখ্যাটি minimum এ চলে এল। সেটি এখন ara2 তে রাখি: ara2[index_2] = minimum। সবশেষে ara2-এর সব সংখ্যা প্রিন্ট করে দেখব। এবারে চলো, পুরো প্রোগ্রামটি লিখে কম্পাইল ও রান করে দেখি আউটপুট কী আসে। 
#include <stdio.h> int main() { int ara1[] = {3, 1, 5, 2, 4}; int ara2[5]; int i, minimum, index_2; for (index_2 = 0; index_2 < 5; index_2++) { minimum = 10000; for (i = 0; i < 5; i++) { if (ara1[i] < minimum) { minimum = ara1[i]; } } ara2[index_2] = minimum; } for (i = 0; i < 5; i++) { printf("%d\n", ara2[i]); } return 0; } প্রোগ্রাম: ১৩.২
কী সুন্দর প্রোগ্রাম! আউটপুট কী? আউটপুটও খুব সুন্দর, একে একে পাঁচটি 1।
1 1 1 1 1
কিন্তু আমরা তো এমন আউটপুট চাইনি। কোথাও গোলমাল হয়েছে। এখন আমার কোডে দেখো তো কোনো ভুল বের করা যায় কি না।
একটি ঝামেলা হয়েছে। ভেতরের লুপে (যেখানে সবচেয়ে ছোট সংখ্যা বের করা হয়) কিন্তু সব সময়ই minimum-এর মান 1 আসবে, কারণ 1 হচ্ছে ওই পাঁচটির মধ্যে সবচেয়ে ছোট সংখ্যা। এজন্য দ্বিতীয় অ্যারেতে পাঁচটি সংখ্যাই 1 হয়ে যাচ্ছে। তাই আমরা যখন minimum বের করব, তখন অ্যারের যেই ঘরে সবচেয়ে ছোট সংখ্যা পাব সেই ঘরের মান একটি অনেক বড় সংখ্যা দিয়ে দেব। এজন্য একটি ভেরিয়েবল রাখি minimum_index। আর লুপটি এখন এমন হবে:
minimum = 10000; for (i = 0; i < 5; i++) { if (ara1[i] < minimum) { minimum = ara1[i]; minimum_index = i; } }
এখন minimum-এর মান আমরা পেয়ে গেছি এবং সেই সঙ্গে এটিও জানি যে এটি আসলে আছে ara1[minimum_index] ঘরে। ara1[minimum_index] = 10000;
তাহলে প্রোগ্রামটি ঠিক করে আবার চালাই:
#include <stdio.h> int main() { int ara1[] = {3, 1, 5, 2, 4}; int ara2[5]; int i, minimum, index_2, minimum_index; for (index_2 = 0; index_2 < 5; index_2++) { minimum = 10000; for (i = 0; i < 5; i++) { if (ara1[i] < minimum) { minimum = ara1[i]; minimum_index = i; } } ara1[minimum_index] = 10000; ara2[index_2] = minimum; } for (i = 0; i < 5; i++) { printf("%d\n", ara2[i]); } return 0; } প্রোগ্রাম: ১৩.৩
এখন প্রোগ্রামটি আউটপুট ঠিকঠাক দেখাবে। আচ্ছা, সব কাজই তো আমি করে দিলাম। তোমাদের কাজটি কী? তোমাদের কাজ হবে প্রোগ্রামটি এমনভাবে লেখা যাতে দ্বিতীয় অ্যারের প্রয়োজন না হয়। শুরুতে যে অ্যারেটি আছে তার ভেতরেই সর্টিং করতে হবে। এজন্য সবচেয়ে ছোট সংখ্যাটি অ্যারের প্রথম ঘরে নিয়ে আসো আর যে ঘর থেকে সবচেয়ে ছোট সংখ্যা পেয়েছ সেখানে প্রথম ঘরের সংখ্যাটি রাখো। এখন তোমার অ্যারের প্রথম ঘরে আছে সবচেয়ে ছোট সংখ্যা। এবারে বাকি চারটি ঘরের মধ্যে সবচেয়ে ছোট সংখ্যাটি অ্যারের দ্বিতীয় ঘরে রাখো এবং যে ঘর থেকে ওই সংখ্যাটি পেয়েছ সেখানে দ্বিতীয় ঘরের সংখ্যাটি রাখো। আর কিছু বলা যাবে না।
রোবট নিয়ে এখন আমরা একটি প্রোগ্রাম লিখব। কোনো একটি N x N গ্রিডে একটি রোবট আছে। শুরুতে তার একটি অবস্থান আছে। আমরা সেটিকে কিছু কমান্ড দেব, এক ঘর ডানে, বাঁয়ে, ওপরে ও নিচে যাওয়ার কমান্ড 

(0, 0) (0, 1) (0, 2) (0, 3) (0, 4) (0, 5) (0, 6) (0, 7) (0, 8) (1, 0)
(1, 2)
(2, 0) (2, 1) R (2, 2) (2, 3)
(3, 0)
(3, 2)
(4, 0)
(5, 0)
(6, 0)
(7, 0)
(8, 0)
(8, 8)
গ্রিডটি দেখো। ওপরের একেবারে বাঁ দিকের ঘর হচ্ছে (0, 0)। ওপরের একেবারে ডানদিকের ঘর হচ্ছে (0, 8)। নিচের একেবারে বাঁ দিকের ঘর হচ্ছে (8, 0)। নিচের একেবারে ডান দিকের ঘর হচ্ছে (8, 8)। ধরা যাক, এই মুহূর্তে রোবটটি আছে (2, 2) ঘরে। এক ঘর ওপরে যেতে বললে সে যাবে (1, 2) ঘরে। নিচে যেতে বললে যাবে (3, 2) ঘরে। ডানে আর বাঁয়ে যেতে বললে যথাক্রমে (2, 3) ও (2, 1) ঘরে যাবে। কমান্ডগুলো হচ্ছে U (up), D (down), L (left), R (right), S (stop)। এখন তোমাকে যদি শুরুর অবস্থান আর কমান্ডগুলো বলে দিই, তাহলে রোবটের শেষ অবস্থান (stop করার পর অবস্থান) বের করতে হবে।
তোমরা কি প্রোগ্রামটি নিজে লিখার জন্য কিছুক্ষণ চেষ্টা করবে?
তোমরা নিশ্চয়ই বুঝতে পারছ যে একটি 2-D অ্যারে দরকার হবে এই প্রোগ্রামে। আসলে কিন্তু এখানে অ্যারের কোনোই দরকার নেই। এটি সাধারণ যোগ-বিয়োগের প্রোগ্রাম। মনে করি, শুরুর অবস্থান হচ্ছে (x, y)। এখন U কমান্ড দিলে একঘর ওপরে যাবে, তখন x-এর মান এক কমে যাবে, y-এর মানের কোনো পরিবর্তন হবে না। D কমান্ড দিলে এক ঘর নিচে যাবে, তখন x-এর মান এক বেড়ে যাবে, y-এর মানের কোনো পরিবর্তন হবে না। R কমান্ড দিলে y-এর মান এক বাড়বে, x-এর মান অপরিবর্তিত থাকবে। L কমান্ড দিলে y-এর মান এক কমবে, x-এর মান অপরিবর্তিত থাকবে। তাহলে আমাদের পুরো প্রোগ্রামটি দাঁড়াবে এই রকম:
#include <stdio.h> int main() { int x, y; char c; printf("Please enter the initial position: "); scanf("%d %d", &x, &y); while (1) { scanf("%c", &c); if (c == 'S') { break; } else if (c == 'U') { x--; } else if (c == 'D') { x++; } else if (c == 'R') { y++; } else if (c == 'L') { y--; } } printf("Final position of the robot is: %d, %d\n", x, y); return 0; } প্রোগ্রাম: ১৩.৪
আউটপুট কী হবে সেটি নির্ভর করবে তোমার ইনপুটের ওপর। যেমন: Please enter the initial position: 2 2 D R D R S Final position of the robot is: 4, 4
বেশ সহজ সরল প্রোগ্রাম। কিন্তু এখন যদি বলি যে গ্রিডে কিছু কিছু ঘরে যাওয়া নিষেধ এবং ওই ঘরগুলোতে যেতে বললে রোবটটি কিছুই করবে না (অর্থাৎ ওই কমান্ডকে উপেক্ষা করবে), তখন আমরা প্রোগ্রামটি কীভাবে লিখব? যেমন একটি উদাহরণ দিই। ধরা যাক, (0, 4) ঘরটি নিষিদ্ধ (blocked)। যদি রোবটের অবস্থান হয় (0, 3) ঘরে এবং তাকে 'R' কমান্ড দেওয়া হয়, তখন তার অবস্থানের কোনো পরিবর্তন হবে না। কারণ এক ঘর ডানে (মানে (0, 4) ঘরে) যাওয়া সম্ভব নয়।
এই সমস্যার সমাধান করতে যে প্রোগ্রামটি লিখতে হবে, তাতে কিন্তু একটি 2-D অ্যারে ব্যবহার করতে হবে। এই অ্যারের সাহায্যে আমরা বুঝব যে কোন ঘরে যাওয়া যাবে আর কোন ঘরে যাওয়া যাবে না। সেটি কীভাবে? খুবই সহজ। যেসব ঘরে যাওয়া যাবে অ্যারের ওই ঘরগুলোতে 1 আর যেসব ঘরে যাওয়া যাবে না সেগুলোতে 0 রাখব।
প্রথমে 10 x 10 গ্রিডের জন্য একটি 2-D অ্যারে ডিক্লেয়ার করি: int grid[10][10];
তারপর শুরুতে ধরে নিই সব ঘরে যাওয়া যাবে।
for (i = 0; i < 10; i++) { for (j = 0; j < 10; j ++) { grid[i][j] = 1; } }
এখন কোন কোন ঘরগুলোতে যাওয়া যাবে না তা ব্যবহারকারীর কাছ থেকে ইনপুট নিই:
printf("Please enter the number of blocked cells: "); scanf("%d", &n); printf("Now enter the cells: "); for (i = 0; i < n; i++) { scanf("%d %d", &x, &y); grid[x][y] = 0; }
এখন কোনো ঘরে যাওয়া যাবে কি না, সেটি বোঝার জন্য একটি শর্ত পরীক্ষা করলেই হবে।
if (grid[x][y] == 1) { যদি সত্য হয়, তবে (x, y) ঘরে যাওয়া যাবে। }
এখন তোমরা সম্পূর্ণ প্রোগ্রামটি নিজে নিজে লিখে ফেলো
Share:

প্রোগ্রামিং স্ট্রিং (string)

প্রোগ্রামিং  স্ট্রিং (string)
তোমরা যারা string শব্দটির বাংলা অর্থ জানো, তাদের আতঙ্কিত হওয়ার কোনো কারণ নেই, প্রোগ্রামিংয়ে স্ট্রিং মোটেও দড়ি টানাটানির মতো কষ্টকর ব্যাপার নয়। আবার তোমাদের মধ্যে যারা একটু জ্ঞানী টাইপের তাদের মাথায় হয়তো স্ট্রিং থিওরী শব্দটি চলে এসেছে। যা-ই হোক, উদ্বেগের কোনো কারণ নেই।
এক বা একাধিক character মিলে string তৈরি হয়। সোজা কথায় স্ট্রিং হচ্ছে ক্যারেক্টার টাইপের অ্যারে। তবে প্রোগ্রামিংয়ে এটির ব্যবহার এতই বেশি যে কোনো কোনো ল্যাঙ্গুয়েজে স্ট্রিংকে আলাদা একটি ডাটা টাইপ হিসেবে ধরা হয়। তবে সি-তে আমরা char টাইপের অ্যারে দিয়েই স্ট্রিংয়ের কাজ করব।
নিচের উদাহরণগুলো লক্ষ করো:
char country[11] = {'B', 'a', 'n', 'g', 'l', 'a', 'd', 'e', 's', 'h', '\0'}; char country[] = {'B', 'a', 'n', 'g', 'l', 'a', 'd', 'e', 's', 'h', '\0'}; char country[] = "Bangladesh"; char *country = "Bangladesh";
এভাবে আমরা স্ট্রিং ডিক্লেয়ার করতে পারি। চারটি ডিক্লারেশন আসলে একই জিনিস। সবার শেষে একটি Null character ('\0') দিলে কম্পাইলার বুঝতে পারে এখানেই স্ট্রিংয়ের শেষ। আবার তৃতীয় উদাহরণে অ্যারের উপাদানগুলো আলাদা করে লেখা হয়নি, একসঙ্গে লেখা হয়েছে। এ ক্ষেত্রে কম্পাইলার নিজেই Null character বসিয়ে নেবে। চতুর্থ উদাহরণটি একটু অদ্ভুত। এখানে যে জিনিসটা ব্যবহার করা হয়েছে তার নাম পয়েন্টার (pointer)। এ বইতে এরকম জিনিস আমরা মাঝে মাঝে ব্যবহার করলেও বিস্তারিত আলোচনায় যাব না।
এবারে প্রোগ্রাম লিখার পালা।
#include <stdio.h> int main() { char country[] = {'B', 'a', 'n', 'g', 'l', 'a', 'd', 'e', 's', 'h', '\0'}; printf("%s\n", country); return 0; } প্রোগ্রাম: ৯.১
এখানে লক্ষ করো যে printf-এর ভেতরে %s ব্যবহার করা হয়েছে স্ট্রিং প্রিন্ট করার জন্য। আর অ্যারেতে শেষের '\0'টা ব্যবহার না করলেও চলে আসলে। বর্তমানের কম্পাইলারগুলো এটি বুঝে নিতে পারে।
#include <stdio.h> int main() { char country[] = {'B', 'a', 'n', 'g', 'l', 'a', 'd', 'e', 's', 'h', ' ', 'i', 's', ' ', 'm', 'y', ' ', 'c', 'o', 'u', 'n', 't', 'r', 'y'}; printf("%s\n", country); return 0; } প্রোগ্রাম: ৯.২
প্রোগ্রামটি চালাও। তারপর নিচের প্রোগ্রামটি চালাও। আউটপুটে কি পার্থক্য দেখতে পাচ্ছ? পার্থক্যের কারণটা কী?
#include <stdio.h> int main() { char country[] = {'B', 'a', 'n', 'g', 'l', 'a', 'd', 'e', 's', 'h', '\0', 'i', 's', ' ', 'm', 'y', ' ', 'c', 'o', 'u', 'n', 't', 'r', 'y'}; printf("%s\n", country); return 0; } প্রোগ্রাম: ৯.৩
পার্থক্যটা কী সেটি তোমরা প্রোগ্রাম দুটি কম্পিউটারে চালালেই বুঝবে। পার্থক্যের কারণ হচ্ছে দ্বিতীয় প্রোগ্রামে স্ট্রিংয়ের ভেতরে এক জায়গায় '\0' থাকায় কম্পাইলার ধরে নিচ্ছে ওখানে স্ট্রিংটা শেষ হয়ে গেছে।
এবারে আমরা একটি প্রোগ্রাম লিখব। একটি স্ট্রিংয়ের ভেতরের সব অক্ষরকে বড় হাতের অক্ষরে (অর্থাৎ capital letter বা uppercase character) রূপান্তর করা। তবে এর জন্য আমাদের একটি জিনিস জানতে হবে। প্রতিটি অক্ষরের বিপরীতে কম্পিউটার একটি সংখ্যার কোড ব্যবহার করে। সেই কোড অনুযায়ী, 'A'-এর মান হচ্ছে 65, 'B'-এর মান হচ্ছে 66, 'C'-এর মান হচ্ছে 67... এভাবে 'Z'-এর মান হচ্ছে 90। তেমনই 'a' হচ্ছে 97, 'b' হচ্ছে 98 ... এভাবে 'z' হচ্ছে 122। সুতরাং কোনো ক্যারেক্টার বড় হাতের কি না সেটি আমরা নির্ণয় করতে পারি এভাবে: if(ch >= 'A' && ch <= 'Z') অথবা if(ch >= 65 && ch <= 90)। তেমনই ছোট হাতের অক্ষরের জন্য: if(ch >= 'a' && ch <= 'z') অথবা if(ch >= 97 && ch <= 122)। এখন কোনো ক্যারেক্টার যদি ছোট হাতের হয়, তবে তাকে বড় হাতের অক্ষরে রূপান্তর করার উপায় কী? উপায় খুব সহজ। একটি উদাহরণ দেখো: char ch = 'c'; ch = 'A' + (ch – 'a'); এখানে যেটি হচ্ছে, প্রথমে ch থেকে 'a' বিয়োগ করা হচ্ছে মানে 'c' থেকে 'a' বিয়োগ (আসলে 99 থেকে 97 বিয়োগ হচ্ছে)। বিয়োগফল 2। এবারে 'A'-এর সঙ্গে যদি ওই 2 যোগ করে দিই তবে সেটি 'C' হয়ে যাবে! এখন প্রোগ্রামটি লিখে ফেলা যাক:
#include <stdio.h> int main() { char country[] = {'B', 'a', 'n', 'g', 'l', 'a', 'd', 'e', 's', 'h'}; int i, length; printf("%s\n", country); length = 10; for(i = 0; i < length; i++) { if(country[i] >= 97 && country[i] <= 122) { country[i] = 'A' + (country[i] - 'a'); } } printf("%s\n", country); return 0; } প্রোগ্রাম: ৯.৪
এখন তোমরা uppercase থেকে lowercase-এ রূপান্তরের প্রোগ্রামটি লিখে ফেলো। তারপরে আবার বইটি পড়া শুরু করো।
এখানে লক্ষ করো যে স্ট্রিংয়ে (ক্যারেক্টারের অ্যারেতে) মোট কয়টি উপাদান আছে সেটি আমি দেখেই লিখে ফেলেছি এবং সরাসরি বসিয়ে দিয়েছি length = 10।
এবার আমরা কোনো স্ট্রিংয়ের দৈর্ঘ্য মাপার জন্য একটি ফাংশন লিখব! এটি তেমন কঠিন কিছু নয়। একটি লুপের সাহায্যে স্ট্রিংয়ের প্রতিটি উপাদান পরীক্ষা করতে হবে এবং Null character ('\0') পেলে লুপ থেকে বের হয়ে যাবে অর্থাৎ, '\0' না পাওয়া পর্যন্ত লুপ চলতে থাকবে। আর লুপ যতবার চলবে স্ট্রিংয়ের দৈর্ঘ্যও তত হবে।
#include <stdio.h> int string_length(char str[]) { int i, length = 0; for(i = 0; str[i] != '\0'; i++) { length++; } return length; } int main() { char country[100]; int length; while(1 == scanf("%s", country)) { length = string_length(
char str[]) { int i, length = 0; for(i = 0; str[i] != '\0'; i++) { length++; } return length; } int main() { char country[100]; int length; while(1 == scanf("%s", country)) { length = string_length(country); printf("length: %d\n", length); } return 0; } প্রোগ্রাম: ৯.৫
ওপরের প্রোগ্রামটায় তোমরা দেখতে পাচ্ছ যে ইনপুট নেওয়ার জন্য scanf ফাংশন ব্যবহার করা হয়েছে এবং স্ট্রিং ইনপুট নেওয়ার জন্য %s ব্যবহৃত হয়েছে। scanf ফাংশনটি যতটি উপাদান ইনপুট হিসেবে নেয়, সেই সংখ্যাটি রিটার্ন করে। সাধারণত রিটার্ন ভ্যালুটি আমাদের দরকার হয় না, তাই scanf ব্যবহার করলেও আমরা ওই ভ্যালুটি রাখি না। যেমন দুটি ইন্টিজার ইনপুট নিতে গেলে আমরা লিখি: scanf("%d %d", &n1, &n2);। আমরা এটি চাইলে এভাবেও লিখতে পারতাম: value = scanf("%d %d", &n1, &n2);। তোমরা প্রিন্ট করলে দেখবে value-এর মান 2। while(1 == scanf("%s", country)) লাইনে যেটি ঘটছে তা হলো, যতক্ষণ একটি country-এর নাম scanf দিয়ে ইনপুট নেওয়া হচ্ছে, ফাংশনটি 1 রিটার্ন করছে, আর লুপের ভেতরের কন্ডিশন সত্য হচ্ছে (1 == 1), তাই লুপের কাজ চলতে থাকবে।
আরেকটি জিনিস খেয়াল করো যে country-এর আগে কোন & চিহ্ন ব্যবহার করা হয়নি। তোমরা &country লিখে দেখো প্রোগ্রামটি কী আচরণ করে। তবে %s ব্যবহারের একটি সমস্যা হচ্ছে স্ট্রিংয়ে কোনো হোয়াইটস্পেস ক্যারেক্টার (যেমন: স্পেস, ট্যাব ইত্যাদি) থাকা যাবে না, এমন কিছু পেলে scanf ওই ক্যারেক্টার পর্যন্ত একটি স্ট্রিং ধরে নেয়। যেমন, ইনপুট যদি হয় this is তবে scanf প্রথমে thisকেই স্ট্রিং হিসেবে নেবে, তারপরে যদি আবার scanf ফাংশন কল করা হয়, তবে isকে সে স্ট্রিং হিসেবে ইনপুট নিয়ে নেবে। এই সমস্যা এড়ানোর জন্য আমরা gets ফাংশন ব্যবহার করতে পারি। নিচের উদাহরণটি দেখো:
#include <stdio.h> int main() { char ara[100]; while(NULL != gets(ara)) { printf("%s\n", ara); } return 0; } প্রোগ্রাম: ৯.৬
এই প্রোগ্রামটিও চলতে থাকবে যতক্ষণ না তুমি ctrl + z (মানে কি-বোর্ডে ctrl ও z একসঙ্গে) চাপো, লিনাক্সের জন্য ctrl + d। ctrl + z বা ctrl + d দিলে gets ফাংশনটি NULL রিটার্ন করে। আরেকটি জিনিস লক্ষ করো যে আমি char ara[100]; ডিক্লেয়ার করে শুরুতেই বলে দিয়েছি স্ট্রিংয়ের সর্বোচ্চ দৈর্ঘ্য হবে 100।
আরেকটি ব্যাপার। string_length ফাংশনের ভেতরে আসলে দুটি ভেরিয়েবল ব্যবহার না করলেও চলে। আমরা ফাংশনটি এভাবেও লিখতে পারি:
int string_length(char str[]) { int i; for(i = 0; str[i] != '\0'; i++); return i; }
এখন তোমাদের কাজ হবে string_length ফাংশনটি for লুপ ব্যবহার না করে while লুপ ব্যবহার করে লেখা।
আমাদের পরবর্তী প্রোগ্রামের লক্ষ্য হবে দুটি স্ট্রিং জোড়া দেওয়া বা concatenate করা। যেমন একটি স্ট্রিং যদি হয় "bangla" এবং আরেকটি স্ট্রিং যদি হয় "desh" তবে দুটি জোড়া দিয়ে "bangladesh" বানাতে হবে।
প্রথমেই স্ট্রিংগুলো ডিক্লেয়ার করে নেই: char str1[] = "bangla", str2[] = "desh", str3[12];
আমাদের লক্ষ হচ্ছে str3তে "bangladesh" রাখা। খুব সুবিধা হতো যদি আমরা এমন কিছু লিখতে পারতাম
: str3 = str1 + str2;
কিন্তু 'সি'-তে এভাবে দুটি অ্যারে বা স্ট্রিং যোগ করা যায় না। তাই একটি একটি করে str1-এর উপাদানগুলো str3তে কপি করতে হবে, তারপর str2-এর উপাদানগুলো str3তে কপি করতে হবে।
#include <stdio.h> int main() { char str1[] = "bangla", str2[] = "desh", str3[12]; int i, j, length1 = 6, length2 = 4; for(i = 0, j = 0; i < length1; i++, j++) { str3[j] = str1[i]; } for(i = 0, j = 0; i < length2; i++, j++) { str3[j] = str2[i]; } str3[j] = '\0'; printf("%s\n", str3); return 0; } প্রোগ্রাম: ৯.৭
প্রোগ্রামটি চালাও। আউটপুট কী আসা উচিত? bangladesh। কিন্তু আউটপুট এসেছে desh। আসলে আমরা কিছু একটা ভুল করেছি। তোমাদের এখন সেই ভুলটি ঠিক করার চেষ্টা করা উচিত। অন্তত তিরিশ মিনিট চেষ্টার পরও যদি ভুল বের করতে না পারো তবে আবার বইটি পড়া শুরু করো।
for(i = 0, j = 0; i < length1; i++, j++) { str3[j] = str1[i]; }
এখানে আমরা শুরুতেই i-এর মান 0 করেছি কারণ iকে আমরা str1-এর ইনডেক্স হিসেবে ব্যবহার করব। jকে ব্যবহার করব str3-এর ইনডেক্স হিসেবে তাই j-এর মানও 0 করা হয়েছে। তারপর একে একে str1-এর উপাদানগুলো str3তে কপি করছি এবং i ও j-এর মান 1 করে বাড়াচ্ছি (i++, j++)। লুপ শেষ হওয়ার পরে i ও j প্রত্যেকের মান হবে 6।
এখন পরের লুপে আমরা str2কে str3-তে কপি করব। এখন str2-এর ইনডেক্স হিসেবে যদি i ব্যবহার করি, তবে তার মান লুপের শুরুতেই আবার 0 করে দিতে হবে। আমরা সেটি করেছি। কিন্তু ভুল করেছি সেই সঙ্গে j-এর মান 0 করে দিয়ে। j-এর মান 0 করলে তো str2-এর প্রথম (0তম) উপাদান str3-এর প্রথম (0তম) উপাদান হিসেবে কপি হবে, কিন্তু আমরা তো সেটি চাই না। আমরা চাই str2-এর প্রথম উপাদান হবে str3-এর সপ্তম উপাদান। তাহলে j-এর মান 0 করা যাবে না। তাই দ্বিতীয় লুপটি হবে এমন:
for(i = 0; i < length2; i++, j++) { str3[j] = str2[i]; }
আরেকটি ব্যাপার লক্ষ করো। দ্বিতীয় লুপ থেকে বের হবার পরে str3-এর শেষ ঘরে '\0' অ্যাসাইন করেছি (str3[j] = '\0'wink emoticon যাতে স্ট্রিংটা যে ওখানেই শেষ, এটি কম্পাইলার বুঝতে পারে।
আমাদের পরবর্তী প্রোগ্রাম হবে দুটি স্ট্রিংয়ের মধ্যে তুলনা করা। অর্থাৎ দুটি স্ট্রিংয়ের মধ্যে ছোট, বড়, সমান নির্ণয় করা। সংখ্যার ক্ষেত্রে যেমন >, <, >=, <=, == চিহ্ন ব্যবহার করে তুলনা করা যায়, স্ট্রিংয়ের ক্ষেত্রে সেই ব্যবস্থা নাই। কিন্তু স্ট্রিংয়ের ক্ষেত্রে প্রায়ই আমাদের এই তুলনা করার দরকার পড়বে। যেমন ধরো, সর্টিংয়ের ক্ষেত্রে যেখানে ছোট থেকে বড় বা বড় থেকে ছোট ক্রমানুসারে সাজাতে হবে (alphabetical ordering)। স্ট্রিংয়ে ছোট-বড় আবার কী? বেশি কথা বলে ব্যাখ্যা না করে কিছু উদাহরণ দিই, তাহলেই বুঝতে পারবে। 'aaa'-এর চেয়ে 'aab' বড়। আবার 'ba' ও 'ca'-এর মধ্যে 'ca' বড়। এই প্রোগ্রামে আমরা একটি ফাংশন লিখব string_compare() যেটির কাজ হবে দুটি স্ট্রিংয়ের মধ্যে তুলনা করে প্রথমটি দ্বিতীয়টির চেয়ে বড় হলে 1 রিটার্ন করবে, ছোট হলে -1 আর দুটি সমান হলে 0 রিটার্ন করবে। ফাংশনের রিটার্ন টাইপ হবে ইন্টিজার এবং প্যারামিটার হবে দুটি char টাইপের অ্যারে। 
int string_compare(char a[], char b[]) {
}
আমাদের মূল কাজ হবে a-এর প্রথম উপাদানের সঙ্গে b-এর প্রথম উপাদান, a-এর দ্বিতীয় উপাদানের সঙ্গে b-এর দ্বিতীয় উপাদান এভাবে তুলনা করতে থাকা। যখনই a-এর কোনো উপাদান b-এর কোনো উপাদানের চেয়ে ছোট হবে, আমরা সঙ্গে সঙ্গে বলে দিতে পারি যে a, b-এর চেয়ে ছোট। সুতরাং -1 রিটার্ন করে ফাংশন থেকে বের হয়ে আসব। একইভাবে যখনই a-এর কোনো উপাদান b-এর কোনো উপাদানের চেয়ে বড় হবে, সঙ্গে সঙ্গে 1 রিটার্ন করে ফাংশন থেকে বের হয়ে আসব কারণ a, b-এর চেয়ে বড়। কিন্তু যদি সবগুলোই সমান হয়? তখন আমরা 0 রিটার্ন করব। তাতে বুঝব যে স্ট্রিং দুটি সমান।
int string_compare(char a[], char b[]) { int i, j; for(i = 0; a[i] != '\0' && b[i] != '\0'; i++) { if(a[i] < b[i]) { return -1; } if(a[i] > b[i]) { return 1; } } if(string_length(a) == string_length(b)) { return 0; } if(string_length(a) < string_length(b)) { return -1; } if(string_length(a) > string_length(b)) { return 1; } }
স্ট্রিংয়ের বেসিক জিনিসগুলো নিয়ে আলোচনা করলাম। তবে মজার ব্যাপার হচ্ছে সি ল্যাঙ্গুয়েজে একটি হেডার ফাইল আছে, যার নাম string.h এবং ওইখানে বেশিরভাগ স্ট্রিং-সংক্রান্ত কাজের জন্য ফাংশন তৈরি করে দেওয়া আছে (যেমন: strcmp, strlen, strcpy ইত্যাদি)। তোমাদের দিয়ে কাজগুলো আমি আবার করালাম বলে দুঃখ পাওয়ার কোনো কারণ নেই, আমার ওপর রাগ করারও কিছু নেই। মৌলিক জিনিসগুলো শিখে রাখা সব সময়ই গুরুত্বপূর্ণ, যা তোমার প্রোগ্রামিং চিন্তাকে বিকশিত করবে।
এখন আমরা আরেকটি প্রোগ্রাম লিখব যেটি ইনপুট হিসেবে একটি স্ট্রিং নেবে (যেখানে অনেকগুলো শব্দ থাকবে)। এই স্ট্রিংয়ের সর্বোচ্চ দৈর্ঘ্য হবে 1000। শব্দগুলোর মাঝখানে এক বা একাধিক স্পেস থাকবে। আউটপুট হিসেবে প্রতিটি শব্দ আলাদা লাইনে প্রিন্ট করতে হবে। বিরামচিহ্নগুলো (punctuation) প্রিন্ট করা যাবে না এবং শব্দের প্রথম অক্ষর হবে বড় হাতের।
অনেক শর্ত দিয়ে ফেললাম। তবে প্রোগ্রামটি খুব কঠিন কিছু নয়। নিজে নিজে চেষ্টা করতে পারো। আর না পারলে এখন চলো দেখি কীভাবে সমাধান করা যায়।
প্রথম কথা হচ্ছে, ইনপুট নেব কীভাবে? বুঝতেই পারছ যে ইনপুটে যেহেতু স্পেস থাকবে, scanf("%s") ব্যবহার করা যাবে না। তাই আমরা gets() ব্যবহার করব। তার পরের কথা হচ্ছে একটি শব্দে কোন কোন ক্যারেক্টার থাকতে পারে
অ্যারে।
int string_compare(char a[], char b[]) {
}
আমাদের মূল কাজ হবে a-এর প্রথম উপাদানের সঙ্গে b-এর প্রথম উপাদান, a-এর দ্বিতীয় উপাদানের সঙ্গে b-এর দ্বিতীয় উপাদান এভাবে তুলনা করতে থাকা। যখনই a-এর কোনো উপাদান b-এর কোনো উপাদানের চেয়ে ছোট হবে, আমরা সঙ্গে সঙ্গে বলে দিতে পারি যে a, b-এর চেয়ে ছোট। সুতরাং -1 রিটার্ন করে ফাংশন থেকে বের হয়ে আসব। একইভাবে যখনই a-এর কোনো উপাদান b-এর কোনো উপাদানের চেয়ে বড় হবে, সঙ্গে সঙ্গে 1 রিটার্ন করে ফাংশন থেকে বের হয়ে আসব কারণ a, b-এর চেয়ে বড়। কিন্তু যদি সবগুলোই সমান হয়? তখন আমরা 0 রিটার্ন করব। তাতে বুঝব যে স্ট্রিং দুটি সমান।
int string_compare(char a[], char b[]) { int i, j; for(i = 0; a[i] != '\0' && b[i] != '\0'; i++) { if(a[i] < b[i]) { return -1; } if(a[i] > b[i]) { return 1; } } if(string_length(a) == string_length(b)) { return 0; } if(string_length(a) < string_length(b)) { return -1; } if(string_length(a) > string_length(b)) { return 1; } }
স্ট্রিংয়ের বেসিক জিনিসগুলো নিয়ে আলোচনা করলাম। তবে মজার ব্যাপার হচ্ছে সি ল্যাঙ্গুয়েজে একটি হেডার ফাইল আছে, যার নাম string.h এবং ওইখানে বেশিরভাগ স্ট্রিং-সংক্রান্ত কাজের জন্য ফাংশন তৈরি করে দেওয়া আছে (যেমন: strcmp, strlen, strcpy ইত্যাদি)। তোমাদের দিয়ে কাজগুলো আমি আবার করালাম বলে দুঃখ পাওয়ার কোনো কারণ নেই, আমার ওপর রাগ করারও কিছু নেই। মৌলিক জিনিসগুলো শিখে রাখা সব সময়ই গুরুত্বপূর্ণ, যা তোমার প্রোগ্রামিং চিন্তাকে বিকশিত করবে।
এখন আমরা আরেকটি প্রোগ্রাম লিখব যেটি ইনপুট হিসেবে একটি স্ট্রিং নেবে (যেখানে অনেকগুলো শব্দ থাকবে)। এই স্ট্রিংয়ের সর্বোচ্চ দৈর্ঘ্য হবে 1000। শব্দগুলোর মাঝখানে এক বা একাধিক স্পেস থাকবে। আউটপুট হিসেবে প্রতিটি শব্দ আলাদা লাইনে প্রিন্ট করতে হবে। বিরামচিহ্নগুলো (punctuation) প্রিন্ট করা যাবে না এবং শব্দের প্রথম অক্ষর হবে বড় হাতের।
অনেক শর্ত দিয়ে ফেললাম। তবে প্রোগ্রামটি খুব কঠিন কিছু নয়। নিজে নিজে চেষ্টা করতে পারো। আর না পারলে এখন চলো দেখি কীভাবে সমাধান করা যায়।
প্রথম কথা হচ্ছে, ইনপুট নেব কীভাবে? বুঝতেই পারছ যে ইনপুটে যেহেতু স্পেস থাকবে, scanf("%s") ব্যবহার করা যাবে না। তাই আমরা gets() ব্যবহার করব। তার পরের কথা হচ্ছে একটি শব্দে কোন কোন ক্যারেক্টার থাকতে পারে? যেহেতু বলা নেই, আমরা ধরে নিই 'a' থেকে 'z', 'A' থেকে 'Z' আর '0' থেকে '9' থাকবে।
তার পরের প্রশ্ন হচ্ছে, আমরা কখন বুঝব বা আমাদের প্রোগ্রামকে কীভাবে বোঝাবো যে একটি শব্দ শুরু হয়েছে?-এর জন্য আমরা একটি ভেরিয়েবল রাখতে পারি। ভেরিয়েবলের নাম যদি দিই is_word_started তাহলে এর মান 0 হলে বুঝব শব্দ শুরু হয়নি, শব্দ শুরু হলে এর মান আমরা 1 করে দেব। আবার শব্দ শেষ হলে 0 করে দেব। যখন দেখব শব্দ শুরু হয়ে গেছে (is_word_started-এর মান 1) কিন্তু কোনো ক্যারেক্টারের মান 'a' – 'z' বা 'A' – 'Z', বা '0' – '9' এই রেঞ্জের মধ্যে নেই, তখনই বুঝব শব্দটি শেষ। তোমরা যদি এর আগে প্রোগ্রামটি চেষ্টা করার পরও লিখতে না পারো, এখন চেষ্টা করলে পারবে আশা করি। আমি এখন কোডটি লিখে দেব তবে সেটি দেখার আগে অবশ্যই নিজে করার চেষ্টা করতে হবে।
#include <stdio.h> #include <string.h> int main() { char s[1002], word[100]; int i, j, length, is_word_started; gets(s); length = strlen(s); is_word_started = 0; for (i = 0, j = 0; i < length; i++) { if (s[i] >= 'a' && s[i] <= 'z') { if (is_word_started == 0) { is_word_started = 1; word[j] = 'A' + s[i] - 'a'; // first character is capital j++; } else { word[j] = s[i]; j++; } } else if (s[i] >= 'A' && s[i] <= 'Z') { if (is_word_started == 0) { is_word_started = 1; } word[j] = s[i]; j++; } else if (s[i] >= '0' && s[i] <= '9') { if (is_word_started == 0) { is_word_started = 1; } word[j] = s[i]; j++; } else { if (is_word_started == 1) { is_word_started = 0; word[j] = '\0'; printf("%s\n", word); j = 0; } } } return 0; } প্রোগ্রাম: ৯.৮
প্রোগ্রামটি বুঝতে কি একটু সমস্যা হচ্ছে? সে পরে দেখা যাবে, আগে প্রোগ্রামটি চটপট কম্পিউটারে টাইপ করে ফেলো, কম্পাইল ও রান করো। যারা লিনাক্স ব্যবহার করছ তারা gets() ব্যবহারের কারণে কম্পাইলার থেকে একটি সতর্ক সংকেত (warning) পেতে পারো, পাত্তা দিয়ো না।
ইনপুট হিসেবে যেকোনো কিছু লিখতে পারো। যেমন: This is a test.। আউটপুট কী?
আউটপুট হচ্ছে এই রকম:
This Is A
কী মুশকিল! test গেল কোথায়? এখন তোমার কাজ হবে test-এর নিখোঁজ হওয়ার রহস্যটা তদন্ত করা। তারপর আমি প্রোগ্রামটি ব্যাখ্যা করব।
তোমরা দেখো প্রোগ্রামে আমি স্ট্রিংয়ের দৈর্ঘ্য নির্ণয়ের জন্য strlen ফাংশন ব্যবহার করেছি। আর-এর জন্য আমাকে string.h হেডার ফাইলটি include করতে হয়েছে। ইনপুট হিসেবে স্ট্রিংটা নিলাম s-এ।
আর word রাখার জন্য একটি অ্যারে ডিক্লেয়ার করে রেখেছি। তারপর আমি i = 0 থেকে length পর্যন্ত একটি লুপ চালিয়েছি s-এর ভেতরের প্রতিটি ক্যারেক্টার পরীক্ষা করার জন্য।
if (s[i] >= 'a' && s[i] <= 'z') দিয়ে পরীক্ষা করলাম এটি ছোট হাতের অক্ষর নাকি। যদি ছোট হাতের অক্ষর হয় তবে একটি শব্দের প্রথম অক্ষর কি না সেটি জানতে হবে। কারণ প্রথম অক্ষর হলে ওটাকে আবার বড় হাতের অক্ষরে রূপান্তর করতে হবে। সেই পরীক্ষাটা আমরা করেছি: if (is_word_started == 0) দিয়ে। এটি সত্য হওয়া মানে শব্দ শুরু হয়নি, এটিই প্রথম অক্ষর। তাই আমরা is_word_started-এর মান 1 করে দেব। আর word[j]তে s[i]-এর বড় হাতের অক্ষরটা নেব। তারপর j-এর মান এক বাড়াতে হবে। else if (s[i] >= 'A' && s[i] <= 'Z') এবং else if (s[i] >= '0' && s[i] <= '9') এই দুটি শর্তের ভেতরেই আমরা একই কাজ করি। s[i]কে word[j]তে কপি করি। তাই চাইলে দুটি শর্তকে একসঙ্গে এভাবেও লিখতে পারতাম: else if ((s[i] >= 'A' && s[i] <= 'Z') || (s[i] >= '0' && s[i] <= '9')) তার পরের else-এর ভেতরে ঢোকার মানে হচ্ছে আগের if এবং else if-এর শর্তগুলো মিথ্যা হয়েছে। তাই s[i]-এর ভেতরে যেই ক্যারেক্টার আছে সেটি word-এ রাখা যাবে না। এবং যদি word ইতিমধ্যে শুরু হয়ে গিয়ে থাকে, সেটি শেষ করতে হবে এবং wordটি প্রিন্ট করতে হবে। আর যদি word শুরু না হয়ে থাকে তাহলে কিছু করার দরকার নেই। 
else { if (is_word_started == 1) { is_word_started = 0; word[j] = '\0'; printf("%s\n", word); j = 0; } }
তোমরা কি test-রহস্য সমাধান করতে পেরেছ? তোমরা চেষ্টা করতে থাকো আর আমি এখন প্রোগ্রামটি অন্যভাবে লিখব (এর সঙ্গে test রহস্যের কোনো সম্পর্ক নেই সেটি বলে রাখলাম)।
এখন আমি যেটি করব, প্রোগ্রামটি এমনভাবে লিখব যাতে word অ্যারেটিই ব্যবহার করতে না হয়! একটু চিন্তা করে দেখো। আসলে তো এই অ্যারেটি নিয়ে আমরা কিছু করছি না প্রিন্ট করা ছাড়া। তাই এর আসলে কোনো দরকার নেই।
#include <stdio.h> #include <string.h> int main() { char s[1002], ch; int i, length, is_word_started; gets(s); length = strlen(s); is_word_started = 0; for (i = 0; i < length; i++) { if (s[i] >= 'a' && s[i] <= 'z') { if (is_word_started == 0) { is_word_started = 1; ch = 'A' + s[i] - 'a'; printf("%c", ch); } else { printf("%c", s[i]); } } else if ((s[i] >= 'A' && s[i] <= 'Z') || (s[i] >= '0' && s[i] <= '9')) { if (is_word_started == 0) { is_word_started = 1; } printf("%c", s[i]); } else { if (is_word_started == 1) { is_word_started = 0; printf("\n"); } } } printf("\n"); return 0; } প্রোগ্রাম: ৯.৯
এখন প্রোগ্রামটি বুঝতে চেষ্টা করো এবং বিভিন্ন ইনপুট দিয়ে পরীক্ষা করে দেখো। যেমন: This is test number 9.9
স্ট্রিং-সংক্রান্ত সমস্যাগুলো দেখতে জটিল মনে হলেও আসলে সহজ। আর এ ধরনের সমস্যা সমাধানের যত চর্চা করবে দক্ষতা তত বাড়বে। 
 
                                              ----------------------THE---------------------
Share:

কুকুর বা অন্য জন্তুর কামড়ের পর করণীয়

কুকুর বা অন্য জন্তুর কামড়ের পর করণীয়
 ১। প্রচুর পানি ও ক্ষার যুক্ত সাবান দিয়ে ক্ষতস্থানটি ধুয়ে ফেলুন।
২। অ্যান্টিসেপকি বা পভিডন/হাইড্রোজেন পার আয়োডিন লাগিয়ে দিন।
৩। ক্ষতস্থানটি ঢাকবেন না।
৪। ক্ষতস্থানে হলুদ গুড়া, বাম, পিতলের থালা, চুন, ভেষজ, ঝাল ইত্যাদি কিছুই লাগাবেন না এবং করা পড়া খাওয়াবেন না। কারণ তাতে কোন ও লাভ হয় না বরং ক্ষতস্থানের আর ক্ষতি হয়।
৫। ক্ষতস্থানে যাকা লাগাবেন না বা পোড়াবেন না।
৬। মাদুলি অথবা জাদুটোনায় ভরসা করবেন না।
৭। যতদ্রুত সম্ভব রোগীকে ডাক্তার, ক্লিনিক বা হাসপাতালে পাঠানোর ব্যবস্থা করুন
Share:

প্রোগ্রামিং বাইনারি সংখ্যা

প্রোগ্রামিং  বাইনারি সংখ্যা
আমরা তো দৈনন্দিন জীবনে নানা হিসাব-নিকাশের জন্য দশভিত্তিক (decimal) সংখ্যা পদ্ধতি ব্যবহার করি। কিন্তু কম্পিউটার ব্যবহার করে দুইভিত্তিক বা বাইনারি (binary) সংখ্যা পদ্ধতি। দশভিত্তিক সংখ্যা পদ্ধতিতে আছে মোট দশটি অঙ্ক 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 আর বাইনারিতে দুটি, 0 আর 1। আমরা এই অধ্যায়ে বাইনারি সংখ্যা পদ্ধতির কিছু মৌলিক জিনিস দেখব আর বাইনারি থেকে ডেসিমাল এবং ডেসিমাল থেকে বাইনারি সংখ্যায় রূপান্তর করা শিখব। ডেসিমালে আমরা গণনা করি এভাবে: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, … 19, 20, 21, …, 98, 99, 100, 101 ...। দেখো, যখনই আমরা ডান দিকের ঘরে (এককের ঘরে) দশটি অঙ্ক ব্যবহার করে ফেলি, তখন তার বাঁয়ে দশকের ঘরের অঙ্কের মান এক বাড়াই (আর যদি না থাকে তাহলে 1 বসাই বা 0-এর সঙ্গে 1 যোগ করি আর কি, কারণ 9 আর 09 কিন্তু একই কথা, তাই 09-এর পরবর্তি সংখ্যা হচ্ছে 10), আবার দশকের ঘরে 0 থেকে 9 সব অঙ্ক ব্যবহার করে ফেলার পরে শতকের ঘরের অঙ্কের মান এক বাড়াই (আর যদি না থাকে তাহলে 1 বসাই বা 0-এর সঙ্গে 1 যোগ করি আর কি)। তেমনই বাইনারিতে আমরা গণনা করব এইভাবে: 0, 1, 10, 11, 100, 101, 110, 111, 1000, 1001, 1010, 1011 ...। যেহেতু অঙ্ক মাত্র দুটি, তাই দুটি অঙ্কের ব্যবহার হয়ে গেলেই বাঁ দিকের ঘরে এক বসাতে হয় বা 0-এর সঙ্গে 1 যোগ করতে হয় (বাঁ দিকে তো আমরা ইচ্ছামত শূন্য বসাতে পারি)।
বাইনারি সিস্টেমে অবশ্য আমরা এককের ঘর, দশকের ঘর, শতকের ঘর, সহস্রের ঘর না বলে বলব একের ঘর, দুইয়ের ঘর, চারের ঘর, আটের ঘর। কেন বল তো? একটু চিন্তা করো।
ডেসিমালে যেমন 10 লিখতে দুটি অঙ্ক লাগে, 100 লিখতে তিনটি, 1000 লিখতে চারটি, তেমনই বাইনারিতে দুই লিখতে দুটি (10), চার লিখতে তিনটি (100), আট লিখতে চারটি (1000), ষোল লিখতে পাঁচটি (10000) অঙ্ক ব্যবহার করতে হয়। ডেসিমালে ডান দিকের প্রথম অঙ্ক (100 = 1) হচ্ছে এককের ঘর, দ্বিতীয় অঙ্ক (101 = 10) হচ্ছে দশকের ঘর, তৃতীয় অঙ্ক (102 = 100) হচ্ছে শতকের ঘর, তেমনই বাইনারিতে ডানদিকের প্রথম অঙ্ক (20 = 1) হচ্ছে একের ঘর, পরের অঙ্ক (21 = 2) হচ্ছে দুইয়ের ঘর, তারপর (22 = 4) হচ্ছে চারের ঘর, এই রকম। দশভিত্তিক সংখ্যায় যেমন যোগ, বিয়োগ, গুণ, ভাগ করা যায়, তেমনই বাইনারিতে করা যায়। আসলে যোগ করতে পারলে কিন্তু বাকি কাজ করা কোনো ব্যাপার নয়। আবার বাইনারিতে ভগ্নাংশের ব্যাপার আছে, তবে আমি কেবল পূর্ণসংখ্যা নিয়েই আলোচনা করব।
যোগের ক্ষেত্রে মূল হিসাবগুলো হচ্ছে: 0 + 0 = 0, 0 + 1 = 1, 1 + 0 = 1, 1 + 1 = 10।
ডেসিমালের মতোই হিসাব, 1 + 1 এর ক্ষেত্রে দেখো, দুইয়ের (10) শূন্য এল প্রথমে, হাতে থাকে এক, সেটি পরে লিখলাম। 101 + 101 = কত? প্রথমে একের ঘরের যোগ, 1 + 1 = 10। তাই যোগফলের একের ঘরে বসবে 0 আর হাতে থাকল 1 (carry)। এবারে দুইয়ের ঘরে, 0 + 0 = 0, এখন এই 0-এর সঙ্গে হাতের 1 যোগ করতে হবে। তাহলে যোগফলের দুইয়ের ঘরে বসবে 1। এবারে চারের ঘরের যোগ করলে পাই, 1 + 1 = 10। হাতে কিছু নেই (কোনো carry নেই)। সুতরাং চারের ঘরে বসবে 0 আর 1 বসবে আটের ঘরে। যোগফল: 1010। এবারে বলো 1011 + 1011 = কত? যোগ করে যদি দেখো যোগফল 10110 হয়নি, তাহলে তুমি যোগে কোথাও ভুল করেছ।
বিয়োগের ক্ষেত্রেও ডেসিমালের মতো হিসাব হবে। 0 – 0 = 0, 1 – 0 = 1, 1 – 1 = 0, 0 – 1 = 1।
শেষেরটি খেয়াল করো, 23 – 15 করার সময় আমরা কী করি? তখন 3-এর বাঁয়ে একটি কাল্পনিক 1 ধরে নিই (বা 1 ধার করি), তারপর 13 – 5 = 8 লেখি। আর যেই একটি ধার করলাম, সেটি পরের ঘরে 1-এর সঙ্গে যোগ করে দিই। তেমনই বাইনারিতে 0 – 1 করতে গেলে 0-এর বাঁয়ে একটি এক ধরব, তখন সংখ্যাটি হবে 10 (দুই), এই দুই থেকে এক বাদ দিলে এক থাকবে। পরের ঘরে একটি এক যোগ করতে হবে (যেই সংখ্যাটি বিয়োগ হচ্ছে তার সঙ্গে)। 110 – 101 = কত?
একের ঘরে 0 থেকে 1 বাদ দিলে থাকে 1, এখানে 1 ধার করতে হয়েছে। তাই 101-এর দুইয়ের ঘরে সেটি যোগ করে দেব। তাহলে দুইয়ের ঘরে 1 – 1 = 0, চারের ঘরে 1 – 1 = 0। তাই বিয়োগফল হবে: 001 বা 1। যোগ-বিয়োগ পারলে গুণ-ভাগ না পারার কারণ নেই। ডেসিমালের মতোই নিয়ম।
আবার কোনো ডেসিমাল সংখ্যাকে আমরা নির্দিষ্ট অঙ্ক x 10ওই অঙ্কের অবস্থান-এর যোগফল হিসেবে যেমন লিখতে পারি, বাইনারি সংখ্যাকেও নির্দিষ্ট অঙ্ক x 2ওই অঙ্কের অবস্থান-এর যোগফল হিসেবে লেখা যায়। যেমন: 1903 = 1 x 103 + 9 x 102 + 0 x 101 + 3 x 100। বাইনারি: 10110 = 1 x 24 + 0 x 23 + 1 x 22 + 1 x 21 + 0 x 20। ইংরেজিতে একে বলে Exponential Expression।
এখন কোনো বাইনারি সংখ্যার মান যদি ডেসিমালে বের করতে চাই, তবে প্রথমে বাইনারি সংখ্যাটিকে এক্সপোনেনশিয়াল এক্সপ্রেশন আকারে লিখতে হবে। তারপর গুণফলগুলো ডেসিমালে হিসাব করতে হবে। নিচের উদাহরণটি দেখো:
10110 = 1 x 24 + 0 x 23 + 1 x 22 + 1 x 21 + 0 x 20 = 1 x 16 + 0 x 8 + 1 x 4 + 1 x 2 + 0 x 1 = 16 + 0 + 4 + 2 + 0 = 22
অর্থাৎ বাইনারি 10110 = ডেসিমাল 22। আমরা অনেকক্ষণ কোনো প্রোগ্রামিং করছি না, চলো বাইনারি সংখ্যার ডেসিমাল মান বের করার একটি প্রোগ্রাম লিখে ফেলি। পদ্ধতি তো জানা হয়ে গেছে। এখন গুরুত্বপূর্ণ প্রশ্ন হচ্ছে, বাইনারি সংখ্যা রিড করব কী দিয়ে? আমরা স্ট্রিং ব্যবহার করতে পারি।
char binary[] = "10110";
int len = 5; // স্ট্রিংয়ের দৈর্ঘ্য 5। int decimal = 0; // এখনো কোনো হিসাব করিনি, তাই ধরলাম ডেসিমাল মান 0।
এবারে আমরা একটি লুপের সাহায্যে বাইনারি সংখ্যার প্রতিটি অঙ্কের সঙ্গে 2ওই অঙ্কের অবস্থান গুণ করে সেটি ডেসিমালের সঙ্গে যোগ করে দেব। প্রথম ক্যারেক্টার অর্থাৎ binary[0]তে তো '1' আছে,-এর অবস্থান কত বলো তো?-এর অবস্থান হচ্ছে 4। তারপরের অঙ্কের বেলায় অবস্থানের মান এক কমবে, এভাবে একেবারে শেষের অঙ্কের বেলায় অবস্থান হবে 0। int position = 4; int indx; for(indx = 0; indx < len; indx++) { decimal = decimal + pow(2, position); position--; }
লুপ থেকে বের হলে আমরা সম্পূর্ণ বাইনারি সংখ্যার ডেসিমাল মান পেয়ে যাব। এখানে দেখো, আমি pow ফাংশন ব্যবহার
করেছি। এটির কাজ বলা আছে math.h হেডার ফাইলে। ab-এর মান বের করার জন্য pow(a, b) বলে দিলেই হয়। তাহলে আমাদের পুরো প্রোগ্রামটি দাঁড়াচ্ছে এই রকম: #include <stdio.h> #include <string.h> #include <math.h> int main() { char binary[65]; int len, decimal, power, i; printf("Enter the binary number: "); scanf("%s", binary); decimal = 0; len = strlen(binary); power = len - 1; for(i = 0; i < len; i++) { decimal += pow(2, power); power--; } printf("Decimal value is %d\n", decimal); return 0; } প্রোগ্রাম: ১২.১

প্রোগ্রাম কম্পাইল করে রান করো। ইনপুট যদি 10110 দাও, তাহলে আউটপুট কত আসে? আউটপুট আসে 31 কিন্তু আউটপুট তো আসা উচিত 22। তাহলে আমরা কোথাও ভুল করেছি। তোমরা নিজে নিজে ভুলটি বের করার চেষ্টা করো।
আমাদের তো আসলে pow(2, position)কে বাইনারি সংখ্যার ওই position-এর অঙ্কটি দিয়ে গুণ করার কথা, সেটি আমরা করতে ভুলে গেছি। অর্থাৎ আমাদের লিখতে হবে:
decimal += binary[i] * pow(2, power);
একটি ব্যাপার খেয়াল করছো তো? 10110-এর একের ঘরের অঙ্কটি আমাদের অ্যারের শেষ ক্যারেক্টার, আর ষোলোর ঘরের অঙ্কটি হচ্ছে অ্যারের প্রথম ক্যারেক্টার। অ্যারেতে সংখ্যাটি আছে এইভাবে: ['1', '0', '1', '1', '0']। তাই binary[0]-এর সঙ্গে গুণ হবে pow(2, 4), binary[1]-এর সঙ্গে গুণ হবে pow(2, 3), …, এভাবে binary[4]-এর সঙ্গে গুণ হবে pow(2, 0)। এখন প্রোগ্রামটি ঠিক করে নিয়ে তারপর চালাও। ইনপুট 10110-এর জন্য কী আউটপুট?
আমি তো আউটপুট দেখতে পাচ্ছি Decimal value is 1510। ভুলটি কোথায় হলো? সব তো ঠিকই করলাম। তোমরা আবার বিরক্ত হয়ে যাচ্ছ না তো? টেস্ট ক্রিকেট খেলার সময় যেমন ধৈর্যের প্রয়োজন, প্রোগ্রামিংও তেমনই ধৈর্যের খেলা।
ভুলটি যে decimal += binary[i] * pow(2, power); স্টেটমেন্টে হয়েছে তাতে কোনো সন্দেহ নেই। কারণ আমরা এখানেই একটু পরিবর্তন করেছি। লক্ষ করো, binary[i]-এর মান হয় '0' বা '1' (মানে ক্যারেক্টার '0' বা ক্যারেক্টার '1')। এখন কম্পিউটার '0' বলতে বোঝে 48 আর '1' বলতে বোঝে 49। ঝামেলাটা এখানেই হয়েছে। এখন এই '0'কে 0 আর '1'কে 1 বোঝাব কীভাবে?
'0' – '0' = 48 – 48 = 0। '1' – '0' = 49 – 48 = 1।
বুদ্ধিটা দারুণ না? আমরা binary[i] না লিখে (binary[i] – '0') লিখলেই ঝামেলা শেষ। এবারে প্রোগ্রাম ঠিকঠাক কাজ করবে (যদি না তুমি নতুন কোনো ভুল করে থাকো)।
এবারে আমরা দেখব ডেসিমাল থেকে বাইনারিতে রূপান্তর। একটি উদাহরণের সাহায্যে পদ্ধতিটা দেখাই। ধরো 95কে বাইনারিতে রূপান্তর করতে হবে। এখন আমাদের বের করতে হবে n-এর সর্বোচ্চ মান, যেখানে 2n <= 95। দুইয়ের পাওয়ারগুলো হচ্ছে 1, 2, 4, 8, 16, 32, 64, 128, ...। এখানে আমরা দেখতে পাচ্ছি 64 < 95 বা 26 < 95। তাহলে n-এর মান 6। আর আমাদের বাইনারি সংখ্যাটি হবে সাত অঙ্কের (0 থেকে 6 মোট সাতটি অঙ্ক)। যেহেতু 64 < 95, তাই এই সংখ্যাটি নেওয়া যায়। তাহলে চৌষট্টির ঘরে (বাঁ থেকে প্রথম বা ডান থেকে সপ্তম) হবে 1 (1xxxxxx)। এখন n-এর মান 1 কমাই। 64 + 25 = 64 + 32 = 96, যা কিনা 95-এর চেয়ে বড়। তাই একে নেওয়া যাবে না। অতএব বত্রিশের ঘরে 0 বসাই (10xxxxx)। এবারে n-এর মান আবার এক কমাই, n-এর মান এখন 4। 64 + 24 = 64 + 16 = 80 < 95। সুতরাং ষোলোর ঘরে হবে 1 (101xxxx)। এখন n-এর মান এক কমাই, n = 3। 80 + 23 = 80 + 8 = 88 < 95। তাই আটের ঘরেও 1 বসবে (1011xxx)। এরপর একইভাবে, n = 2-এর জন্য 88 + 22 = 88 + 4 = 92 < 95। চারের ঘরেও 1 বসবে (10111xx)। তারপর n = 1, 92 + 21 = 92 + 2 = 94 < 95। দুইয়ের ঘরেও 1 (101111x)। এখন n = 0, 94 + 20 = 94 + 1 = 95। তাই একের ঘরেও 1। সুতরাং বাইনারি সংখ্যাটি হচ্ছে 1011111। তোমরা এখন এই পদ্ধতিতে কোনো দশভিত্তিক সংখ্যাকে বাইনারিতে রূপান্তর করার প্রোগ্রাম লিখে ফেলো এবং বিভিন্ন মান দিয়ে পরীক্ষা করে দেখো।
এখন একই কাজ আমরা একটু অন্যভাবে করব। নিচের টেবিলটি দেখো:
ভাগফল
 ভাগশেষ
95/ 2 47 1 47/2 23 1 23/2 11 1 11/2 5 1 5/2 2 1 2/2 1 0 1 /2 0 1
এবারে ভাগশেষ কলামের অঙ্কগুলো শেষ থেকে প্রথম ক্রমে লেখলেই আমরা বাইনারি নম্বরটা পেয়ে যাব: 1011111। আর ভাগের কাজটি আমরা ততক্ষণ করব যতক্ষণ না ভাগফল 0 পাচ্ছি। এই পদ্ধতিতেও তোমরা ডেসিমাল থেকে বাইনারি রূপান্তরের জন্য একটি কোড লিখে ফেলো। রূপান্তরের কোডটি main ফাংশনে না করে আলাদা একটি ফাংশনে করবে
Share:

প্রোগ্রামিং বাইনারি সার্চ

প্রোগ্রামিং বাইনারি সার্চ
একটি সহজ খেলা দিয়ে শুরু করা যাক। এটি খেলতে দুজন দরকার। একজন মনে মনে একটি সংখ্যা ধরবে। আর দ্বিতীয়জন কিছু প্রশ্ন করে সেই সংখ্যাটি বের করবে। তবে 'তোমার সংখ্যাটি কত?' - এমন প্রশ্ন কিন্তু সরাসরি করা যাবে না। প্রশ্নটি হচ্ছে: সংখ্যাটি কি N (একটি সংখ্যা)-এর চেয়ে বড়, ছোট নাকি সমান?
আর সংখ্যাটি কিন্তু একটি নির্দিষ্ট সীমার মধ্যে হতে হবে (যেমন 1 থেকে 100, 10 থেকে 1000, -1000 থেকে 100000)। এখন ধরা যাক, প্রথমজন যে সংখ্যাটি ধরেছে সেটি 1 থেকে 1000-এর ভেতর একটি সংখ্যা। তাহলে কিন্তু সর্বোচ্চ এক হাজার বার 'সংখ্যাটি কি N-এর সমান?' প্রশ্নটি করে সেটি বের করে ফেলা যায়। (সংখ্যাটি কি 1? সংখ্যাটি কি 2? ... সংখ্যাটি কি 999?, সংখ্যাটি কি 1000?)। এভাবে প্রশ্ন করতে থাকলে সংখ্যাটি অবশ্যই বের হবে। তবে ভাগ্য খারাপ হলে এক হাজার বার ওই প্রশ্নটি করতে হবে।
কিন্তু আমাদের তো এত সময় নেই। ধরা যাক, 1 থেকে 1000-এর ভেতর ওই সংখ্যাটি হচ্ছে 50। তাহলে আমাদের প্রথম প্রশ্ন হবে: ১) সংখ্যাটি কি 500-এর চেয়ে বড়, ছোট নাকি সমান? ছোট। ২) সংখ্যাটি কি 250-এর চেয়ে বড়, ছোট নাকি সমান? ছোট। ৩) সংখ্যাটি কি 125-এর চেয়ে বড়, ছোট নাকি সমান? ছোট। ৪) সংখ্যাটি কি 62-এর চেয়ে বড়, ছোট নাকি সমান? ছোট। ৫) সংখ্যাটি কি 31-এর চেয়ে বড়, ছোট নাকি সমান? বড়। ৬) সংখ্যাটি কি 46-এর চেয়ে বড়, ছোট নাকি সমান? বড়। ৭) সংখ্যাটি কি 54-এর চেয়ে বড়, ছোট নাকি সমান? ছোট। ৮) সংখ্যাটি কি 50-এর চেয়ে বড়, ছোট নাকি সমান? সমান। আমরা মাত্র আটটি প্রশ্ন করেই সংখ্যাটি পেয়ে গেছি!
তোমরা নিশ্চয়ই পদ্ধতিটি বুঝে ফেলেছ? প্রতিবার প্রশ্ন করে সংখ্যাটি যে সীমার মধ্যে আছে তাকে অর্ধেক করে ফেলা হয়েছে। খেলা শুরুর সময় সীমাটি ছিল 1 থেকে 1000। তারপর সেটি হয়েছে 1 থেকে 500। তারপর 1 থেকে 250, 1 থেকে 125, 1 থেকে 62, 31 থেকে 62, 46 থেকে 62, 46 থেকে 54।
সংখ্যা খুঁজে বের করার এই পদ্ধতিকে বলে বাইনারি সার্চ। চলো আমরা তাহলে অ্যালগরিদমটি লিখার চেষ্টা করি: বাইনারি সার্চ (low, high, N): (শুরুতে আমাদের তিনটি সংখ্যা জানতে হবে, সংখ্যাটির নিম্নসীমা (low), উচ্চসীমা (high) এবং সেই সংখ্যা (N)) ধাপ 1: mid = (low + high) / 2 ধাপ 2: যদি mid এবং N-এর মান সমান হয় তবে ধাপ 5-এ যাও। ধাপ 3: যদি N, mid-এর চেয়ে বড় হয়, তাহলে low = mid + 1. ধাপ 1-এ যাও। ধাপ 4: যদি N, mid-এর চেয়ে ছোট হয়, তাহলে high = mid - 1. ধাপ 1-এ যাও। ধাপ 5: সংখ্যাটি পেয়ে গেছি (mid)।
এখন আমরা দেখব একটি অ্যারে থেকে কীভাবে বাইনারি সার্চ করে কোনো সংখ্যা খুঁজে বের করতে হয়। অ্যারেতে কিন্তু সংখ্যাগুলো ছোট থেকে বড় কিংবা বড় থেকে ছোট ক্রমানুসারে থাকতে হবে। নইলে বাইনারি সার্চ ব্যবহার করা যাবে না। কারণটি কি কেউ বলতে পারো? প্রথমে আমরা একটি ইন্টিজার অ্যারে নিই যেখানে সংখ্যাগুলো ছোট থেকে বড় ক্রমানুসারে সাজানো আছে। int ara[] = {1, 4, 6, 8, 9, 11, 14, 15, 20, 25, 33 83, 87, 97, 99, 100};
এখন বলো তো low আর high-এর মান কত হবে? low = 1 এবং high = 100 ? ঠিকই ধরেছ কিন্তু এখানে একটু সমস্যা আছে। আমরা এখানে সব সংখ্যার মধ্যে খুঁজব না, বরং অ্যারের ইনডেক্সের মধ্যে খুঁজব। আর অ্যারের ইনডেক্সগুলো ক্রমানুসারে থাকে বলেই অ্যারেতে বাইনারি সার্চ করা যায়। এখানে ara-এর সর্বনিম্ন ইনডেক্স হচ্ছে 0 এবং সর্বোচ্চ ইনডেক্স হচ্ছে 15। তাহলে আমরা দুটি ভেরিয়েবলের মান নির্দিষ্ট করে দিই - low_indx = 0; high_indx = 15; যে সংখ্যাটি খুঁজব ধরা যাক সেটি হচ্ছে 97। num = 97;
তোমাদের অনেকেই হয়তো ভাবছ, num সংখ্যাটি যদি ara-তে না থাকে তখন কী হবে? সেটিও আমরা দেখব। সংখ্যাটি যদি খুঁজে পাওয়া না যায় তবে সেটি জানিয়ে দেওয়ার ব্যবস্থা রাখতে হবে আমাদের প্রোগ্রামে।
আমাদের যেহেতু খোঁজার কাজটি বারবার করতে হবে, আমাদেরকে একটি লুপ ব্যবহার করতে হবে। লুপের ভেতর আমরা খোঁজাখুঁজি করব আর সংখ্যাটি পেয়ে গেলে (কিংবা সংখ্যাটি নেই সেটি নিশ্চিত হলে) আমরা লুপ থেকে বের হয়ে যাব। while(1) { mid_indx = (low_indx + high_indx) / 2; if(num == ara[mid_indx]) { /* num যদি ara[mid_indx]-এর সমান হয়, তবে সেটি আমরা পেয়ে গেছি */ break; } if(num < ara[mid_indx]) { /* num যদি ara[mid_indx]-এর ছোট হয়, তবে আমরা low_indx থেকে mid_indx – 1 সীমার মধ্যে খুঁজব। */ high_indx = mid_indx – 1; } else { /* num যদি ara[mid_indx]-এর বড় হয়, তবে আমরা mid_indx + 1 থেকে high_indx সীমার মধ্যে খুঁজব। */ low_indx = mid_indx + 1; } } বাইনারি সার্চের প্রোগ্রাম আমরা লিখে ফেললাম। খুবই সহজ-সরল প্রোগ্রাম। সংখ্যাটি খুঁজে না পাওয়া পর্যন্ত লুপটি চলতেই থাকবে, কারণ আমরা লিখেছি while(1) আর 1 সব সময় সত্যি। কিন্তু সংখ্যাটি যদি ara-তে না থাকে তবে লুপটি চলতেই থাকবে এবং আমাদের প্রোগ্রাম কখনো বন্ধ হবে না। সুতরাং একটা ব্যবস্থা করা দরকার। আচ্ছা, আমরা কীভাবে বুঝব যে সংখ্যাটি ara-তে নেই? তোমরা ইতিমধ্যে লক্ষ করেছ যে আমরা প্রতিবার সার্চের সীমাটা অর্ধেক করে ফেলি। এভাবে চলতে থাকলে একসময় ওই সীমার ভেতর একটি সংখ্যাই থাকবে। তখন low এবং high-এর মান সমান হবে। আর প্রতিবার যেহেতু হয় low-এর মান বাড়ছে নাহয় high-এর মান কমছে, সুতরাং যেবার low আর high সমান হবে, তার পরের বার low-এর মান high-এর মানের চেয়ে বেশি হবে। তখন আমরা বুঝব যে সংখ্যাটি খুঁজে পাওয়া যায়নি। সুতরাং যতক্ষণ low <= high ততক্ষণ লুপটি চলবে। লুপ থেকে বের হয়ে যদি দেখি low > high, তখন বুঝব যে সংখ্যাটি খুঁজে পাওয়া যায়নি, আর না হলে বুঝব সংখ্যাটি খুঁজে পাওয়া গেছে এবং-এর মান ara[mid_indx]।
তাহলে পুরো প্রোগ্রামটি এবারে লিখে ফেলা যাক: #include <stdio.h> int main() { int ara[] = {1, 4, 6, 8, 9, 11, 14, 15, 20, 25, 33 83, 87, 97, 99, 100}; int low_indx = 0; int high_indx = 15; int mid_indx
]।
তাহলে পুরো প্রোগ্রামটি এবারে লিখে ফেলা যাক: #include <stdio.h> int main() { int ara[] = {1, 4, 6, 8, 9, 11, 14, 15, 20, 25, 33 83, 87, 97, 99, 100}; int low_indx = 0; int high_indx = 15; int mid_indx; int num = 97; while (low_indx <= high_indx) { mid_indx = (low_indx + high_indx) / 2; if (num == ara[mid_indx]) { break; } if (num < ara[mid_indx]) { high_indx = mid_indx – 1; } else { low_indx = mid_indx + 1; } } if (low_indx > high_indx) { printf("%d is not in the array\n", num); } else { printf("%d is found in the array. It is the %d th element of the array.\n", ara[mid_indx], mid_indx); } return 0; } প্রোগ্রাম: ৮.১ এবার তোমাদের কাজ হবে বাইনারি সার্চের জন্য একটি আলাদা ফাংশন লেখা।
আর বাইনারি সার্চ কীভাবে কাজ করে, সেটি এখানে সুন্দর করে অ্যানিমেশনের মাধ্যমে বোঝানো হয়েছে: http://video.franklin.edu/Franklin/Math/170/common/mod01/binarySearchAlg.html
Share:

ত্রিভুজাকার রহস্য

ত্রিভুজাকার রহস্য 
বারমুডা ট্রায়াঙ্গল’ বারমুডা ট্রায়াঙ্গল ! পৃথিবীর রহস্যময় স্থানগুলোর তালিকা করা হলে সে তালিকার প্রথম দিকে থাকবে এই নামটি । রহস্যময়, ভূতুড়ে, গোলমেলে, অপয়া সব বিশেষণই বারমুডা ট্রায়াঙ্গলের জন্য উপযুক্ত । সারা বিশ্বজুড়ে সব চাইতে অলোচিত রহস্যময় অঞ্চল হচ্ছে এই বারমুডা ট্রায়াঙ্গল । এর রহস্য উদঘাটনের জন্য অসংখ্য গবেষণা চালানো চয়েছে, এই স্থানকে নিয়ে অন্তর্জাতিক গনমাধ্যমে অসংখ্য প্রতিবেদন প্রকাশিত হয়েছে, বিভিন্ন টিভি চ্যানেল তৈরি করেছে ডকুমেন্টারি । তবু আজো এই স্থানটির রহস্যময়তার নেপথ্যে কি রয়েছে তা জানা সম্ভব হয় নি ।
বারমুডা ট্রায়াঙ্গল এলাকাটি আটলান্টিক মহাসাগরের একটি বিশেষ ত্রিভুজাকার অঞ্চল যেখান বেশ কিছু জাহাজ ও উড়োজাহাজ রহস্যজনক ভাবে নিখোঁজ হয়ে গেছে চিরদিনের জন্য । কিন্তু সত্যিকার অর্থে বারমুডা ট্রায়াঙ্গলের ভৌগলিক অবস্থান নির্দিষ্ট নয় । কেউ মনে করেন এর আকার ট্রাপিজয়েডের মত যা ছড়িয়ে আছে স্ট্রেইটস অব ফ্লোরিডা, বাহামা এবং ক্যারিবিয়ান দ্বীপপূঞ্জ এবং ইশোর পূর্বদিকের আটলান্টিক অঞ্চল জুড়ে । আবার কেউ কেউ এগুলোর সাথে মেক্সিকোর উপসাগরকেও যুক্ত করেন । তবে লিখিত বর্ণনায় যে সকল অঞ্চলের ছবি ফুটে ওঠে তাতে বোঝা যায় ফ্লোরিডার আটলান্টিক উপকূল, সান হোয়ান, পর্তু রিকো, মধ্য আটলান্টিকে বারমুডার দ্বীপপূঞ্জ এবং বাহামা ও ফ্লোরিডা স্ট্রেইটস এর দক্ষিণ সীমানা জুড়ে এটি বিস্তৃত ।
বারমুডা ট্রায়াঙ্গলের বিষয়ে বিভিন্ন লেখক রেফারেন্স হিসেবে সর্বপ্রথম ক্রিস্টোফার কলম্বাসের কথা উল্লেখ করেছেন । কলম্বাস লিখেছিলেন যে তাঁর জাহাজের নবিকেরা এই অঞ্চলের দিগন্তে আলোর নাচানাচি এবং আকাশে ধোঁয়া দেখেছেন । এছাড়া তিনি এখানে কম্পাসের উল্টাপাল্টা দিক নির্দেশনার কথাও বর্ণনা করেছেন । এরপরেও অসংখ্য ঘটনা বিশ্ববাসীর সামনে এসেছে বারমুডা ট্রায়াঙ্গলকে কেন্দ্র করে ।
১৯৪৫ সালের ডিসেম্বর মাস মার্কিন যুক্তরাষ্ট্রের ৫টি যুদ্ধ বিমান প্রশিক্ষণ নেবার জন্য উদ্দয়ন করে । কিছুক্ষণ পরেই তারা সেই ভয়ংকর বারমুডা ট্রায়াঙ্গলের কাছে চলে যায় এবং কেন্দ্রে ম্যাসেজ দেয় যে তারা সামনে আর কিছুই দেখতে পারছে না যতদূর চোখ যাচ্ছে শুধুই কুয়াশা । অদৃশ্য হবার শেষ মুহূর্তে তাদের শেষ কথা ছিল “আমাদের বাঁচাও, উদ্ধার কর এখান থেকে আকাশের কুয়াশা আমাদের কোথায় যেন নিয়ে যাচ্ছে !”
এর পর আর তাদের কাছ কোন ধরনের ম্যাসেজ পাওয়া যায়নি । পরবর্তীতে তাদের উদ্ধার করার জন্য একটি উদ্ধারকারী দল সেদিকে পাঠানো হয় কিন্তু তাদেরকেও আর খুজে পাওয়া যায় নি । এর পরপরই বারমুডা ট্রায়াঙ্গল আলোচনার কেন্দ্রবিন্দুতে পরিণত হয় ।
১৯৫০ সালের সেপ্টেম্বর মাসের ১৬ তারিখে অ্যাসোসিয়েট প্রেসের এক প্রবন্ধে সাংবাদিক ই ভি ডাবলিউ জোনস বারমুডা ট্রায়াঙ্গেলের অস্বাভাবিক ঘটনার কথা লিখে একে বিশ্ববাসীর নজরে আনেন । ১৯৫২ সালে ‘ফেট’ ম্যাগাজিন-এর জর্জ এক্স সান্ড লিখেন “সি মিসট্রি অ্যাট আওয়ার ব্যাক ডোর”। জর্জ এক্স সান্ড ৫ জন ইউএস নেভি সহ ১৯ নং ফ্লাইটের নিখোঁজ সংবাদ ছাপেন । শুরু হয় বারমুডা রহস্য !
১৯৫৯ সালের ১৭ জানুয়ারী স্টার এরিয়েল নামের একটি বিমান লন্ডন থেকে জ্যামাইকা যাচ্ছিল । সকাল ৭টা ৪৫ মিনিটে এটি বারমুডার আকাশে উড়ল । তখন আবহাওয়া ছিল স্বাভাবিক ও সুন্দর । আর সমুদ্র ছিল শান্ত । ওড়ার ৫৫ মিনিট পর বিমানটি অদৃশ্য হয়ে গেল । এ নিয়ে অনেক অনুসন্ধান হলো । কিন্তু সমুদ্রের কোথাও বিমানটির ধ্বংসাবশেষ খুঁজে পাওয়া গেল না । বিমানটি অদৃশ্য হয়েছিল ১৭ জানুয়ারি রাতে । ১৮ তারিখ রাতে এক অনুসন্ধানী দল জানাল, সেখানকার সমুদ্রের বিশেষ বিশেষ একটি জায়গা থেকে অদ্ভূত একটি আলোর আভাস দেখা যাচ্ছে । এ ঘটনার এক বছর আগে সেখান থেকে রহস্যজনকভাবে অদৃশ্য হয়ে গিয়েছিল একটি ডিসি-৩ বিমান । সেটি যাচ্ছিল সানজুয়ান থেকে সিয়ামি । এছাড়াও অসংখ্য ঘটনার উল্লেখ আছে বারমুডা ট্রায়াঙ্গলকে নিয়ে ।
এই স্থানটি নিয়ে আরেকটি গুজব আছে, অনেকেই মনে করে ভিনগ্রহের মানুষেরা যখন পৃথিবীত আসে তখন তারা এই স্থানকে তাদের ঘাটি বানিয়ে নেয় এই কারনে এখানে যা কিছু আসবে সেটি গায়েব করে দিবে যাতে করে তাদের কেউ ক্ষতি বা চিহ্ন খুজে না পায় ।
এই অঞ্চলের রহস্যময়তার একটি দিক হলো, কোনো জাহাজ এই ত্রিভুজ এলাকায় প্রবেশ করার কিছুক্ষণের মধ্যেই তা বেতার তরঙ্গ প্রেরণে অক্ষম হয়ে পড়ে এবং এর ফলে জাহাজটি উপকূলের সঙ্গে যোগাযোগ স্থাপনে ব্যর্থ হয় । একসময় তা দিক নির্ণয় করতে না পেরে রহস্যজনকভাবে অদৃশ্য হয়ে যায় ।
মার্কিন নেভির সূত্র অনুযায়ী, গত ২০০ বছরে এ এলাকায় কমপক্ষে ৫০টি বাণিজ্যিক জাহাজ এবং ২০টি বিমান চিরতরে অদৃশ্য হয়ে গেছে । এর মধ্যে ১৯৬৮ সালের মে মাসে হারিয়ে যাওয়া মার্কিন যুক্তরাষ্ট্রের পারমাণবিক ডুবোজাহাজের ঘটনাটি সারা বিশ্বে সবচাইতে বেশি আলোড়ন তোলে । ঘটনা তদন্তে এর মধ্যে সবচাইতে বিজ্ঞানসম্মত যে ব্যাখ্যা পাওয়া গেছে তা হলো, এলাকাটির স্বাভাবিক বৈশিষ্ট্য হচ্ছে এখানে স্বাভাবিকের চাইতে কুয়াশা অনেক বেশি এবং এর ঘনত্বও তুলনামূলকভাবে বেশি । ফলে নাবিকেরা প্রবেশের পরই দিক হারিয়ে ফেলে এবং তাদের মধ্যে একপ্রকার বিভ্রান্তির সৃষ্টি হয়। হয়তো এ বিভ্রান্তির ফলেই তারা যথাযথভাবে বেতার তরঙ্গ পাঠাতে পারে না । প্রমাণ হিসেবে বিজ্ঞানীরা দেখিয়েছেন, আধুনিক কালের সমস্ত জাহাজ জিএসএম প্রযুক্তি ব্যবহার করে থাকে, তাদের একটিও এ সমস্যায় পড়েনি ।
আর ধংসাবশেষ খুজে না পাবার ব্যপারে বিজ্ঞানীরা বলেন, বারমুডা ট্রায়াঙ্গলে সমুদ্রের গভীরতা এতোটাই বেশি যে এখানে যদি কোন বিমান বা জাহাজ হারিয়ে যায় বা বিধ্বস্ত হয় তবে তার ধংসাবশেষ খুজে পাওয়া খুবই অসাধ্য একটি ব্যাপার । বর্তমানে আধুনিক প্রযুক্তি যেমন স্যাটেলাইট ব্যবহার করে যদি এর চিহ্ন খুজে পাওয়া যায় তারপরেও সেটি উদ্ধার করা প্রায় অসম্ভব একটি ব্যাপার ।
Share:

Pages

Theme Support