রং অ্যানসার

যারা বিভিন্ন প্রোগ্রামিং সমস্যা সমাধানের ওয়েবসাইটে কেবল চর্চা করা শুরু করেছ, তাদের জন্য সবচেয়ে সাধারণ ব্যাপার হচ্ছে এই রং অ্যানসার (Wrong Answer)। “স্যাম্পল ইনপুট-আউটপুটের সাথে তো আমার মিলে, তাহলে অনলাইন জাজ কেন রং অ্যানসার দিচ্ছে”?

58306615নমুনা ইনপুট-আউটপুট (Sample Input-Output) মিললেই হবে না। ধরা যাক, কোনো একটা প্রাইম নাম্বার বের করার প্রোগ্রামে নমুনা ইনপুট দেওয়া আছে 3, 5, 7 যার জন্য আউটপুট হচ্ছে প্রাইম। এখন এটা দেখে কেউ যদি এমন প্রোগ্রাম লেখে যে বিজোড় সংখ্যা মাত্রই প্রাইম, তাহলে তো হবে না, তাই না? তাই নিজে নিজে টেস্ট কেইস তৈরি করে আগে নিজে বের করতে হবে যে আউটপুট কী হবে। তারপরে প্রোগ্রামের আউটপুটের সাথে মিলিয়ে দেখবে।

আরেকটা ব্যাপার হচ্ছে আউটপুট ফরম্যাটিং। প্রতিটা টেস্ট কেইসের শেষে নিউলাইন (“\n”) দিতে হবে, যেটা আসল বলে দেওয়া থাকে না। আর দেখতে হবে নমুনা আউটপুটের সাথে যেন হুবুহু মিলে। ছোটহাত-বড়হাতের অক্ষর (Uppercase / lowerse) এবং স্পেস ক্যারেক্টার ঠিকমতো মিলতে হবে। যেমন প্রবলেমের আউটপুটে যদি Case লিখতে বলে আর তুমি case লিখ, তাহলে হবে না। আবার Case 1: লিখতে বললে তুমি যদি Case 1 : লিখ (: এর আগে একটি স্পেস), তাহলেও রং অ্যানসার।

কর্ণার কেস টেস্ট করতে হবে। ধরা যাক তোমাকে বলা হল, a ^ n -এর মান বের করতে। এখন তুমি চট করে প্রোগ্রাম লিখে ফেললে যেটা খুব সহজেই কাজটি করে দেয়। স্যাম্পল আউটপুট তো মিলেই, তুমি নিজেও যেসব ইনপুট-আউটপুট তৈরি করে টেস্ট করলে, সেগুলোও মিলে যায়। কিন্তু এখানে n-এর মান 0 হলে কী হবে? আর ঋণাত্মক হলেই বা কী হবে? এগুলোও কিন্তু তোমার প্রোগ্রামে ঠিকঠাক আউটপুট দিতে হবে।

আরেকটি কারণ হচ্ছে সমস্যার বর্ণনা ঠিকমতো বুঝতে না পারা। আমরা অনেক সময় একবার বা দুবার পড়ে ঠিকঠাক বুঝতে পারি না। তাই রং অ্যানসার হলে সমস্যার বর্ণনা আবার মনোযোগ দিয়ে পড়তে হবে। অনেক সময় দেখবে তখন তুমি উপলব্ধি করবে যে প্রোগ্রাম লেখার সময় তুমি সমস্যাটি ঠিকঠাক বুঝতে পারো নি।

অনেক সময় ফ্লোটিং পয়েন্ট নাম্বার নিয়ে ক্যালকুলেশনের সময় ঝামেলা হয়। সবকিছু ঠিকঠাক থাকলেও ফ্লোটিং পয়েন্ট ক্যালকুলেশনের কারণে তুমি রং অ্যানসার পেতে পার। তাই এই কাজটি ঠিকঠাক করতে হবে। নিচে একটি উদাহরণ দিচ্ছি (পাইথন কোড) :

>>> 2.1 – 1.9
0.20000000000000018

তাই ফ্লোটিং পয়েন্ট নিয়ে কাজ করার সময় সাবধান।

আরেকটা কারণ হচ্ছে ভুল অ্যালগরিদমের ব্যবহার। এটাও আসলে সমস্যার বর্ণনা ঠিকভাবে বুঝতে না পারার ফলেই ঘটে থাকে।
এসব সমস্যা থেকে পরিত্রাণ পাওয়ার উপায় হচ্ছে রং অ্যানসার খেলে সেটা যে তোমারই ভুল, এটা স্বীকার করে নেওয়া (মাঝে-মধ্যে জাজেরও ভুল হতে পারে, তবে সেটা খুবই কম ঘটে)। নিজে আরো চিন্তাভাবনা করা, না পারলে বন্ধুদের সাথে সেটা নিয়ে আলাপ করা। তাতেও কাজ না হলে অনলাইন ফোরাম ঘেঁটে দেখা যে আগে কেউ এরকম সমস্যায় পরেছে কী না এবং সেটা কিভাবে সমাধান হয়েছে।

বিগ ইন্টিজার ২

BigInteger এর মেথড
জাভার BigInteger ক্লাসে অনেক গুলো মেথড আছে, যা ব্যবহার করে আমরা বিগ-ইন্টিজার দিয়ে অনেক বড় বড় সমস্যা খুব সহজেই সমাধান করে ফেলতে পারি। আমি এখানে প্রয়োজনীয় কিছু মেথড নিয়ে আলচনা করছি।

যোগ / বিয়োগ / গুণ / ভাগ করা
দুটি বিগ-ইন্টিজার যোগ করার জন্য আমাদেরকে add() মেথডটি ব্যবহার করতে হবে। ধরা যাক, আমরা a এবং b দুটি সংখ্যা যোগ করে ans নামের একটি ভেরিয়েবলে রাখতে চাই। তাহলে আমাদের লিখতে হবে –
BigInteger ans = a.add(b);

একই ভাবে বিয়োগ করার জন্য subtract(), গুণ করার জন্য multiply(), এবং ভাগ করার জন্য আমাদেরকে divide() মেথড ব্যবহার করতে হবে।

ভাগশেষ বের করা
একটি সংখ্যা কে অপর একটি সংখ্যা দিয়ে ভাগ করার পর অবশিষ্ট ভাগশেষ বা mod ভ্যালু বের করতে চাইলে আমাদেরকে mod() মেথড টি ব্যবহার করতে হবে। যেমন, আমরা যদি একটি সংখ্যা a কে অপর একটি সংখ্যা m দিয়ে mod করতে চাই তাহলে আমাদের লিখতে হবে-
BigInteger ans = a.mod(m);

এছাড়াও remainder() মেথড দিয়েও একই কাজ করা যায়।

তুলনা করা
অন্য সব ডাটা টাইপের মত বিগ ইন্টিজারে আমরা দুটি সংখ্যা তুলনা করার জন্য ==, > বা < ব্যবহার করতে পারি না। দুটি বিগ-ইন্টিজার সমান কিনা তা দেখার জন্য আমাদের equals() মেথড টি ব্যবহার করতে হয়। সংখ্যা দুটি সমান হলে মেথডটি true রিটার্ন করে, তা নাহলে false রিটার্ন করে। দুটি বিগ-ইন্টিজার কম্পেয়ার করার জন্য জাভার BigInteger ক্লাসে compareTo() মেথড আছে। এই মেথডটি একটি ইন্টিজার সংখ্যা রিটার্ন করে। আমরা যখন দুটি সংখ্যা কম্পেয়ার করবো তখন প্রথম সংখ্যাটি যদি দ্বিতীয় সংখ্যার চেয়ে ছোটো হয় তাহলে মেথডটি -1 রিটার্ন করবে, সংখ্যা দুটি যদি সমান হয় তাহলে 0 রিটার্ন করবে এবং প্রথম সংখ্যাটি যদি বড় হয় তাহলে 1 রিটার্ন করবে। নিচের কোডটি রান করে দেখলে বিষয়টি আরো ভালভাবে বুঝা যাবে –

import java.util.*;
import java.math.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner (System.in); 
        BigInteger a, b;
        a = sc.nextBigInteger();
        b = sc.nextBigInteger();
        int cmp = a.compareTo(b);
        if(cmp == -1) 
            System.out.println("a is less than b");
        else if(cmp == 0) 
            System.out.println("a is equal to b");
        else if(cmp == 1) 
            System.out.println("a is greater than b");
    }
}

পাওয়ার বের করা
আমরা চাইলে বিগ-ইন্টিজারের পাওয়ারও বের করতে পারি। এজন্য আমাদেরকে pow() মেথডটি ব্যবহার করতে হবে। তবে এই মেথডটি প্যারামিটার হিসেবে একটি ইন্টিজার গ্রহন করে, তাই পাওয়ার এর মানটি অবশ্যই int ডাটা টাইপের রেঞ্জের মধ্যে হতে হবে। কোনো একটি সংখ্যা n এর পাওয়ার p বের করতে চাইলে আমাদের লিখতে হবে –
BigInteger ans = n.pow(p);

বিগ-মড ভ্যালু বের করা
বিগ-মড বা (n^p)%m এক্সপ্রেশনের মান বের করার জন্য বিগ-ইন্টিজারের modpow() মেথড আছে। মেথডটি প্যারামিটার হিসেবে দুটি BigInteger নিয়ে থাকে। এখন আমরা যদি কোন একটি সংখ্যা n-এর পাওয়ার p-কে অপর একটি সংখ্যা m দিয়ে mod করতে চাই, তাহলে আমাদের লিখতে হবে –

BigInteger ans = n.modPow(p,m);

মডুলার-ইনভার্স ভ্যালু বের করা
মডুলার-ইনভার্স বের করার জন্য বিগ-ইন্টিজারে modInverse() মেথড আছে। তবে এজন্য আমরা যে সংখ্যার মডুলার-ইনভার্স বের করতে চাই এবং যে সংখ্যাটি দিয়ে mod করতে চাই, তাদেরকে অবশ্যই রিলেটিভলি-প্রাইম হতে হবে। এখন আমরা যদি কোনো একটি সংখ্যা n-এর মডুলার-ইনভার্স বের করতে চাই এবং যে সংখ্যাটি দিয়ে mod করবো তা যদি m হয়, তাহলে আমাদের লিখতে হবে –
BigInteger ans = n.modInverse(m);

GCD বের করা
দুটি সংখ্যার Greatest Common Divisor (GCD) অর্থাৎ গসাগু বের করার জন্য বিগ-ইন্টিজারে gcd() মেথডটি আছে। দুটি সংখ্যা a এবং b-এর GCD বের করতে চাইলে আমাদের লিখতে হবে –
BigInteger ans = a.gcd(b);

ম্যাক্সিমাম/ মিনিমাম বের করা
জাভার বিগ-ইন্টিজারে দুটি সংখ্যার মধ্যে বৃহত্তর সংখ্যা বের করার জন্য max() এবং ক্ষুদ্রতর সংখ্যা বের করার জন্য min() মেথড রয়েছে। দুটি সংখ্যার মধ্যে ম্যাক্সিমাম বা মিনিমাম বের করার জন্য আমাদের লিখতে হবে –
BigInteger largest = a.max(b);
BigInteger smallest = a.min(b);

Absolute মান বের করা
কোনো সংখ্যার পরম মান বা Absolute value বের করার জন্য বিগ-ইন্টিজারে abs() মেথড আছে। কোনো একটি সংখ্যা n এর Absolute মান বের করতে চাইলে লিখতে হবে –
BigInteger ans = n.abs();

বিগ ইন্টিজার ৩

সম্ভাব্য-মৌলিক সংখ্যা
আমাদের অনেক সময় প্রাইম নাম্বার বের করার প্রয়োজন হতে পারে। বিশেষ করে ক্রিপ্টোগ্রাফীর জন্য প্রাইম নাম্বার জেনারেট করা অনেক জরুরি। একটি বিগ-ইন্টিজার সম্ভাব্য প্রাইম নাম্বার কি না তাও আমরা বের করতে পারি। এজন্য BigInteger ক্লাসে isProbablePrime() মেথড আছে। মেথডটিতে probabilistic primality টেস্টের জন্য Miller–Rabin অ্যালগরিদম ব্যবহার করা হয়েছে। মেথডটি প্যারামিটারে certainty হিসেবে একটি ইন্টিজার ভ্যালু নিয়ে থাকে এবং একটি বুলিয়ান ডাটা রিটার্ন করে। certainty দিয়ে অসম্ভাব্যতার হার বের করা হয়। তারপর তা থেকে সম্ভাব্যতার হার বের করা হয়। সম্ভাব্যতার হার বের করা হয় (1 – 0.5certainty) এভাবে। কোনো একটি সংখ্যা প্রাইম নাম্বার হবার সম্ভাব্যতা যদি এই মানকে অতিক্রম করে তাহলে মেথড টি true রিটার্ন করে, অন্যথায় false রিটার্ন করে। অর্থাৎ certainty এর মান যত বড় হবে, সম্ভাব্যতার হার তত বাড়বে। আবার অন্য দিকে সম্ভাব্যতার হার যত বাড়বে, প্রোগ্রামের এক্সিকিউশন টাইম ততো বেশি লাগবে। তাই এটা ব্যবহারকারীর উপর নির্ভর করে যে সে কতটুকু সময়ের মধ্যে কত সম্ভাব্যতার প্রাইম নাম্বার চায়।
কোন একটি সংখ্যা n, certainty c-এর সাপেক্ষে প্রাইম কি না, বের করতে হলে আমাদের লিখতে হবে –
boolean flag = n.isProbablePrime(c);

আবার কোনো একটি সংখ্যার পরবর্তি কোন সংখ্যাটি একটি সম্ভাব্য প্রাইম, তা বের করার জন্য বিগ ইন্টিজারে আছে nextProbablePrime() মেথড। মেথডটি একটি সম্ভাব্য প্রাইম নাম্বার রিটার্ন করে এবং রিটার্ন করা নাম্বারটি একটি কম্পোজিট নাম্বার হবার সম্ভাব্যতা থাকে 2-100 এর কম। কোনো একটি সংখ্যা n-এর পরবর্তি সম্ভাব্য প্রাইম সংখ্যাটি বের করতে হলে আমাদের লিখতে হবে-
BigInteger ans = n .nextProbablePrime();

আমাদের অনেক সময় র‍্যান্ডম প্রাইম নাম্বারের দরকার হতে পারে। বিগ ইন্টিজারে র‍্যান্ডম ভাবেও সম্ভাব্য প্রাইম নাম্বার জেনারেট করা যায়। এজন্য বিগ ইন্টিজারে probablePrime() মেথড আছে। মেথডটি প্যারামিটারে bitLength হিসেবে একটি ইন্টিজার এবং rnd হিসেবে একটি র‍্যান্ডম ডাটা নিয়ে থাকে। মেথডটির রিটার্ন করা নাম্বারটি এই bitLength-সংখ্যক বিটের হবে। মেথডটি কল করার সময় এর মান সব সময় 2 বা তার বেশি হতে হবে। আর rnd হচ্ছে একটি র‍্যান্ডম বিট সোর্স, একটি সম্ভাব্য প্রাইম নাম্বার রিটার্ন করার জন্য যার primality টেস্ট করা হয়। মেথডটি একটি সম্ভাব্য প্রাইম নাম্বার রিটার্ন করে এবং রিটার্ন করা নাম্বারটি একটি কম্পোজিট নাম্বার হবার সম্ভাব্যতা থাকে 2^-100 এর কম। এখন আমাদের যদি n সংখ্যক বিটের একটি র‍্যান্ডম সম্ভাব্য প্রাইম নাম্বার বের করতে হয়, তাহলে আমাদের লিখতে হবে –
Random rnd = new Random();
BigInteger ans =  BigInteger.probablePrime(n, rnd);

বিগ ইন্টিজার ৪

Bitwise অপারেশন
বিগ ইন্টিজারেও আমরা বিট-ওয়াইজ অপারেশন করতে পারি। এজন্য BigInteger ক্লাসে কিছু বিল্ট-ইন মেথড রয়েছে।

AND (a&b): বিগ ইন্টিজারের বিট-ওয়াইজ AND ভ্যালু বের করার জন্য রয়েছে and() মেথড। দুটি বিগ ইন্টিজার a এবং b-এর AND ভ্যালু বের করতে চাইলে লিখতে হবে –
BigInteger ans = a.and(b);

OR (a|b): বিগ ইন্টিজারের বিট-ওয়াইজ OR ভ্যালু বের করার জন্য রয়েছে or() মেথড। দুটি বিগ ইন্টিজার a এবং b-এর OR ভ্যালু বের করতে চাইলে আমাদের লিখতে হবে –
BigInteger ans = a.or(b);

XOR (a^b): বিগ ইন্টিজারে xor() মেথড টি দিয়ে বিট-ওয়াইজ XOR বা Exclusive OR ভ্যালু বের করা হয়। দুটি বিগ ইন্টিজার a এবং b এর XOR ভ্যালু বের করতে চাইলে আমাদের লিখতে হবে-
BigInteger ans = a.xor(b);

NOT (~a): বিগ ইন্টিজারের বিট-ওয়াইজ NOT ভ্যালু বের করার জন্য রয়েছে not() মেথড। কোন একটি বিগ ইন্টিজার a এর NOT ভ্যালু বের করতে চাইলে আমাদের লিখতে হবে-
BigInteger ans = a.not();

Shift-Left (a<<n): আমরা চাইলে বিগ ইন্টিজারের বিটগুলোকে শিফটও করতে পারি। বিটগুলোকে বাম দিকে শিফট করার জন্য আমাদেরকে shiftLeft() মেথডটি ব্যবহার করতে হবে। মেথডটি প্যারামিটারে একটি ইন্টিজার সংখ্যা নিয়ে থাকে। একটি নাম্বারের বিটগুলোকে আমরা বাম দিকে কত বিট শিফট করবো এটি হচ্ছে তার মান। কোনো একটি সংখ্যা a-কে আমরা যদি n বিট বামে শিফট করতে চাই, তাহলে লিখতে হবে –
BigInteger ans = a. shiftLeft(n);

Shift-Right (a>>n): বিগ ইন্টিজারের বিট গুলো কে ডান দিকে শিফট করার জন্য আমাদেরকে shiftRight() মেথডটি ব্যবহার করতে হবে। এটি shiftLeft() মেথডটির মতই। কোনো একটি সংখ্যা a-কে আমরা যদি n বিট ডানে শিফট করতে চাই, তাহলে লিখতে হবে –
BigInteger ans = a.shiftRight(n);

Test-Bit (a&(1<<n)): একটি বিগ ইন্টিজারের n-তম বিটটি 0 নাকি 1, তা বের করার জন্য BigInteger ক্লাসে আছে testBit() মেথড। মেথডটি প্যারামিটারে n-এর মান নেয় এবং n-তম বিট 1 হলে true রিটার্ন করে, আর 0 হলে false রিটার্ন করে। এখন আমরা যদি কোনো একটি সংখ্যা a-এর n-তম বিট পরীক্ষা করতে চাই, তাহলে লিখতে হবে-
boolean flag = a.testBit(n);

Clear-Bit (a & ~(1<<n)): একটি বিগ ইন্টিজারের কোনো একটি বিটকে 0 করতে হলে আমাদের clearBit() মেথডটি ব্যবহার করতে হবে। কোনো একটি সংখ্যা a-এর n-তম বিটকে 0 করতে চাইলে আমাদের লিখতে হবে-
BigInteger ans = a.clearBit(n);

Set-Bit (a|(1<<n)): একটি বিগ ইন্টিজারের কোনো একটি বিটকে 1 করতে হলে আমাদের setBit() মেথডটি ব্যবহার করতে হবে। কোনো একটি সংখ্যা a-এর n-তম বিটকে 1 করতে চাইলে আমাদের লিখতে হবে –
BigInteger ans = a.setBit(n);

Flip-Bit (a ^ (1<<n)): একটি বিগ ইন্টিজারের কোনো একটি বিটকে ফ্লিপ করতে হলে অর্থাৎ 0 থাকলে 1 করতে অথবা 1 থাকলে 0 করতে চাইলে আমাদের flipBit() মেথডটি ব্যবহার করতে হবে। কোনো একটি সংখ্যা a-এর n-তম বিটকে ফ্লিপ করতে চাইলে আমাদের লিখতে হবে-
BigInteger ans = a.flipBit(n);

AND-NOT (a & ~b): দুটি বিগ ইন্টিজারের বিট-ওয়াইজ AND-NOT ভ্যালু বের করতে চাইলে andNot() মেথডটি ব্যবহার করতে হবে। দুটি বিগ ইন্টিজার a এবং b এর AND-NOT ভ্যালু বের করতে চাইলে আমাদের লিখতে হবে-
BigInteger ans = a.andNot(b);

Lowest Set Bit (log2(a & -a)): কোনো সংখ্যার সবচেয়ে ছোট কোন বিটে 1 আছে, তা বের করার জন্য বিগ ইন্টিজারে getLowestSetBit() মেথড আছে। কোনো একটি বিগ ইন্টিজার a-এর সবচেয়ে ছোট কোন বিটটি 1 তা বের করতে চাইলে আমাদের লিখতে হবে –
int ans = a.getLowestSetBit();

আরো কিছু প্রয়োজনীয় মেথড
toString(): বিগ ইন্টিজার কে স্ট্রিং এ কনভার্ট করতে ব্যবহার করা হয়।
toByteArray(): বিগ ইন্টিজার কে বাইট-অ্যারে তে কনভার্ট করতে ব্যবহার করা হয়।
negate(): বিগ ইন্টিজারের সাইন পরিবর্তন করতে ব্যবহার করা হয়।
bitCount(): কোন সংখ্যার 2’s complement এ সাইন বিটের বিপরীত কয়টি বিট আছে তা বের করার জন্য ব্যবহার করা হয়।
bitLength(): একটি সংখ্যা কে বাইনারি বেইজে রিপ্রেজেন্ট করতে (সাইন বিট ছাড়া) কয়টি বিটের প্রয়োজন তা জানার জন্য ব্যবহার করা হয়।
signum(): কোন সংখ্যা ধনাত্মক, ঋণাত্মক অথবা শূন্য কি না তা জানার জন্য ব্যবহার করা হয়। ধনাত্মক হলে 1, ঋণাত্মক হলে -1 এবং শূন্য হলে মেথড টি 0 রিটার্ন করে।
intValue(): BigInteger থেকে int ডাটায় কনভার্ট করতে ব্যবহার করা হয়। তবে এ ক্ষেত্রে ডাটা ওভারফ্লো হলে মেথড টি কোন এক্সেপশন থ্রো করে না। এক্ষেত্রে intValueExact() ব্যবহার করলে এই মেথড টি এক্সেপশন থ্রো করে।
longValue(): BigInteger থেকে long ডাটায় কনভার্ট করতে ব্যবহার করা হয়। এই মেথড টি ও ডাটা ওভারফ্লো হলে এক্সেপশন থ্রো করে না। এক্ষেত্রে longValueExact() ব্যবহার করলে এই মেথড টি এক্সেপশন থ্রো করে।
floatValue(): BigInteger থেকে float ডাটায় কনভার্ট করতে ব্যবহার করা হয়।
doubleValue(): BigInteger থেকে double ডাটায় কনভার্ট করতে ব্যবহার করা হয়।
hashCode(): হ্যাশ-কোড বের করার জন্য ব্যবহার করা হয়।
divideAndRemainder(): মেথড টি দুটি সংখ্যার ভাগফল এবং ভাগশেষ এক সাথে একটি BigInteger অ্যারে আকারে রিটার্ন করে। রিটার্ন করা অ্যারে টির [0] ইন্ডেক্সে থাকে ভাগফলের মান এবং [1] ইন্ডেক্সে থাকে ভাগশেষ এর মান।

import java.util.*;
import java.math.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner (System.in); 
        BigInteger a=sc.nextBigInteger();
        BigInteger b=sc.nextBigInteger();
        BigInteger arr[] = a.divideAndRemainder(b); 
        System.out.println("Quotient = "+arr[0]);
        System.out.println("Remainder = "+arr[1]); 
    }
}

এই ছিলো আমাদের BigInteger নিয়ে আলোচনা। Java-তে BigDecimal নামে আরো একটি ক্লাস আছে যা দিয়ে Decimal সংখ্যার হিসাব নিকাশ করা যায়। এটির ব্যবহার BigInteger-এর মতোই।

বিগ ইন্টিজার ১

জাভার একটি চমৎকার জিনিস হচ্ছে বিগ ইন্টিজার (BigInteger)। সেটি নিয়ে আমার ব্লগের পাঠকদের জন্য একাধিক পর্বের সিরিজ লিখেছে তুষার রায় (বাংলাদেশ ইউনিভার্সিটি অব বিজনেস এন্ড টেকনোলোজি (বি ইউ বি টি)-তে কম্পিউটার বিজ্ঞান বিভাগে অধ্যয়নরত)।

প্রথম পর্ব

আমরা বিভিন্ন প্রোগ্রামিং ভাষায় হিসাব-নিকাশ করার জন্য সাধারণত int (32-bit) বা long (64-bit) টাইপের ডাটা ব্যবহার করে থাকি। এদের মধ্যে int ডাটা দিয়ে খুব বড় সংখ্যাগুলোর হিসাব-নিকাশ করা না গেলেও long ডাটা দিয়ে মোটামুটি 10^18 এর কাছাকাছি সংখ্যাগুলো এক্সেস করা যায়। সমস্যা হয় তখন যখন আমাদেরকে এর চেয়েও অনেক অনেক বড় সংখ্যা নিয়ে কাজ করার দরকার হয়। তখন আমরা কোনো সাধারণ ডাটা টাইপ দিয়ে সরাসরি এদের হিসাব-নিকাশ করতে পারি না, কারণ এতে করে আমাদের ভেরিয়েবলগুলোতে ডাটার ওভারফ্লো হয়।

এ ধরণের সমস্যা দূর করবার জন্য Java-তে BigInteger নামের একটি বিল্ট-ইন ক্লাস তৈরি করা আছে। যা দিয়ে খুব সহজেই অনেক বড় বড় সংখ্যার হিসাব-নিকাশ করে ফেলা যায়। BigInteger-এর সাইজ JVM-এর পর্যাপ্ত মেমোরির উপর নির্ভর করে। তবে প্রয়োজন ছাড়া এটি ব্যবহার করা উচিত নয়, কারণ BigInteger সাধারন ডাটা-টাইপ এর তুলনায় অনেক ধীরে কাজ করে। এখন তাহলে দেখা যাক, বিগ ইন্টিজার ব্যবহার করে আমরা কী কী কাজ করতে পারি এবং কীভাবে।

প্যাকেজ ইম্পোর্ট করাঃ
BigInteger ক্লাসটি জাভার math প্যাকেজের অন্তর্ভুক্ত। তাই BigInteger ব্যবহার করার জন্য আমাদেরকে প্রথমেই math প্যাকেজটি ইম্পোর্ট করে নিতে হবে।
import java.math.BigInteger;

ভেরিয়েবল ডিক্লেয়ার করাঃ
বিগ ইন্টিজার ভেরিয়েবল ডিক্লেয়ার করা অন্য সব ডাটা টাইপের মতোই। এখানে মূলত BigInteger ক্লাসের অবজেক্ট তৈরি করা হয়। যেমন, আমরা যদি a, b এবং c নামের তিনটি ভেরিয়েবল ডিক্লেয়ার করতে চাই তাহলে আমাদের এভাবে লিখতে হবে –
BigInteger a, b, c;

ইনপুট ও আউটপুটঃ
BigInteger এর ইনপুট ও আউটপুটও অন্য সব ডাটা টাইপের মতো। যেমন, আমরা যদি একটি ভেরিয়েবলের মান ইনপুট নিয়ে তা আউটপুটে দেখাতে চাই তাহলে আমাদের প্রোগ্রাম টি এভাবে লিখতে হবে –

import java.util.*;
import java.math.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner (System.in);
        BigInteger n;
        n = sc.nextBigInteger();
        System.out.println(n);
    }
}

ভ্যালু অ্যাসাইন করাঃ
আমাদেরকে অনেক সময় এক ভেরিয়েবলের মান অন্য ভেরিয়েবলে অথবা সরাসরি কোন মান একটি ভেরিয়েবলে অ্যাসাইন করার প্রয়োজন হতে পারে। এক ভেরিয়েবল থেকে অন্য ভেরিয়েবলে ভ্যালু অ্যাসাইন করতে আমরা সরাসরি ‘=’ ব্যবহার করতে পারি। যেমন, একটি ভেরিয়েবল b-এর মান অপর একটি ভেরিয়েবল a-তে অ্যাসাইন করতে চাইলে হলে লিখতে হবে –
BigInteger a = b;

কিন্তু সরাসরি যদি কোনো মান একটি ভেরিয়েবলে অ্যাসাইন করতে চাই, তাহলে BigInteger এর কন্সট্রাক্টর ব্যবহার করে ভেরিয়েবলে (যেটি আসলে একটি BigInteger অবজেক্ট) তার মান অ্যাসাইন করতে হবে। BigInteger-এর কন্সট্রাক্টরটি প্যারামিটার হিসেবে একটি নাম্বারের স্ট্রিং নিয়ে থাকে। যেমন –
BigInteger n = new BigInteger(“1234567890123456789”);

আবার আমরা BigInteger.valueOf(int_value) ব্যবহার করে যেকোনো ইন্টিজারকে সরাসরি BigInteger হিসেবে ব্যবহার করতে পারি।

BigInteger অ্যারেঃ
BigInteger এর আবার অ্যারে! অবাক হবার কিছু নেই। বিগ-ইন্টিজারের অ্যারেও আমরা ব্যবহার করতে পারি। এটিও অন্য সব ডাটা টাইপের অ্যারের মতোই।
BigInteger[] array_name = new BigInteger[array_size];

এখন আমরা চাইলে এই অ্যারেটি সর্টও করে ফেলতে পারি। সম্পুর্ন অ্যারে সর্ট করতে চাইলে লিখতে হবে Arrays.sort(array_name);, আর কোনো একটা নির্দিষ্ট রেঞ্জের ভ্যালু গুলো সর্ট করতে চাইলে লিখতে হবে Arrays.sort(array_name, fromIndex, toIndex+1);। সর্ট করার ক্ষেত্রে খেয়াল রাখতে হবে যাতে অ্যারেটির কোনো ইন্ডেক্সে নাল ভ্যালু না থাকে, নইলে আমাদের প্রোগ্রামটি এক্সেপশন থ্রো করবে।

দ্বিতীয় পর্ব

তৃতীয় পর্ব

চতুর্থ পর্ব

কোড শেয়ার করার ওয়েবসাইট

বিভিন্ন ওয়েবসাইটে ও ফেসবুক গ্রুপে প্রোগ্রামিং সংক্রান্ত সাহায্যের জন্য অনেকেই পোস্ট করে। আবার অনেকসময় সেসব পোস্টের সাথে কোডও থাকে। কেউ কেউ কোডের স্ক্রিনশট নেয়, কেউ বা সরাসরি কোড পেস্ট করে। এতে কোড দেখতে অনেক বাজে লাগে এবং বোঝা কঠিন হয়ে যায়। ফেসবুকে কমেন্ট আকারে কোড পেস্ট করলে ইনডেন্টেশন নষ্ট হয়ে যায়। আর পাইথনের মতো ল্যাঙ্গুয়েজ যেখানে ইনডেন্টেশন অনেককিছু নিয়ন্ত্রণ করে, সেখানে তো ইনডেন্টেশন না থাকলে তেমন কিছুই বোঝা যায় না। আসলে নিজের কোড অন্যকে সাময়িক সময়ের জন্য দেখাতে চাইলে সবচেয়ে সহজ উপায় হচ্ছে কোড শেয়ার করার ওয়েবসাইটগুলো ব্যবহার করা। এরকম তিনটি ওয়েবসাইটের নাম দিয়ে দিচ্ছি :

১) paste.ubuntu.com

Screenshot from 2015-01-21 02:16:49এখানে নাম লিখতে হবে, প্রোগ্রামিং ল্যাঙ্গুয়েজ সিলেক্ট করতে হবে, কোড পেস্ট করতে হবে, তারপরে Paste! বাটনে ক্লিক করলে যেই নতুন লিঙ্কটি তৈরি হবে, সেটি দিয়েই কোড শেয়ার করা যাবে।

২) pastebin.com

Screenshot from 2015-01-21 02:18:22

এটিও আগেরটির মতোই। তবে পেস্ট এক্সপায়ার করার একটা সময় নির্ধারণ করে দেওয়া যায়। আর বেশি বেশি ব্যবহার করতে হলে একাউন্ট তৈরি করে নিতে হয়।

৩) pastie.org
এটির ব্যবহারও খুব সহজ। এখানে একাউন্ট তৈরি করা লাগে না।

এরকম আরো বেশ কিছু ওয়েবসাইট আছে, গুগলে সার্চ করলেই পেয়ে যাবে – যেকোনো একটি ব্যবহার করলেই চলবে। আশা করছি সবাই এখন থেকে আরো সুন্দরভাবে কোড শেয়ার করবে।

প্রোগ্রামিং সংক্রান্ত বাংলায় প্রশ্নোত্তর করার ভালো ওয়েবসাইট হচ্ছে  http://programabad.com, আর ফেসবুকে আছে প্রোগ্রামিং স্কুল নামে একটি গ্রুপ।

দ্রুপাল কোর আপডেট

drupal_branding_2012আমার মূল ওয়েবসাইট (subeen.com) দ্রুপাল দিয়ে তৈরি। কেন দ্রুপাল বেছে নিয়েছিলাম, তার কারণ হচ্ছে ওইসময় একটা প্রজেক্টে কাজ করতাম যেখানে দ্রুপাল ব্যবহার করতে হয়েছিল, সম্ভবত সেখান থেকে দ্রুপাল ব্যবহার করার উৎসাহ পেয়েছিলাম। ওয়েবসাইটটা মাঝে মাঝে আপডেট করার প্রয়োজন হয়। এর মধ্যে দ্রুপাল কোর যখন আপডেট করতে হয়, সেটা ম্যানুয়ালি করতে হয় এবং আমার গুগল সার্চ করে বের করতে হয়ে কীভাবে আপডেট করে। তাই নিজের ব্লগে বাংলা ভাষায় লিখে রাখলাম, যেন পরবর্তী সময়ে গুগল না করে আমার ব্লগেই আমি সার্চ করতে পারি।

কীভাবে দ্রুপাল (ভার্শন ৭) কোর আপডেট করতে হয়?

দ্রুপাল কোর ম্যানুয়ালি আপডেট করতে হলে নিচের স্টেপগুলো অনুসরণ করতে হবে :

) ডাটাবেজেের ব্যাকআপ নিতে হবে।

) দ্রুপালের বর্তমান ভার্শনের সর্বশেষ রিলিজ ডাউনলোড করে সাইটে আপলোড করতে হবে।

) সাইটে আপলোড করার পরে দ্রুপাল প্যাকেজ আনজিপ করতে হবে।

) ওয়েবসাইটের [yourdrupalsitename]/admin/config/development/maintenance এ গিয়ে সাইটে মেইনটেনেন্স মোডে নিয়ে যেতে হবে।

) দ্রুপালের বর্তমান ব্যবহৃত ইনস্ট্যান্সের /sites ডিরেক্টরি ছাড়া বাকী সব ফাইল ও ডিরেক্টরি মুছে ফেলে নতুন ভার্শনের ফাইল ও ডিরেক্টরিগুলো পেস্ট করে দিতে হবে (sites ডিরেক্টরি ব্যাতীত)

) এরপর সাইটে এডমিন হিসেবে লগিন করে আপডেট স্ক্রিপ্ট চালাতে হবে। ব্রাউজারের এড্রেসবারে সরাসরি এই লিঙ্ক পেস্ট করলে আপডেট স্ক্রিপ্ট চলবে : http://[yourdrupalsitename]/update.php

) আপডেট করা শেষ হলে ওয়েবসাইটকে মেইনটেনেন্স মোড থেকে ফিরিয়ে স্বাভাবিক অবস্থায় আনতে হবে।

বি.দ্র. [yourdrupalsitename] এর জায়গায় নিজের ওয়েবসাইটের নাম দিতে হবে। যেমন আমার ওয়েবসাইটের ক্ষেত্রে subeen.com

লিনাক্স সার্ভারে পাসওয়ার্ড ছাড়া লগইন

আমরা অনেকেই ssh টুল ব্যবহার করে রিমোট লিনাক্স সার্ভারে লগইন করি এবং প্রতিবারই পাসওয়ার্ড দেওয়া লাগে। এই পাসওয়ার্ড দেওয়ার ঝামেলাটা সহজেই এড়ানো যায়। এতে যেই কম্পিউটার থেকে লগিন করা হয়, সেখানে কি (key) তৈরি করে সার্ভারে সেটা দিয়ে দিতে হয়।

Monitor_padlock

এর জন্য নিচের ধাপগুলো অনুসরন করতে হবে :

১) প্রথম কাজ হচ্ছে একজোড়া পাবলিক-প্রাইভেট কি জোড়া (key pair) তৈরি করা। তার জন্য নিচের কমান্ড দিতে হবে :

ssh-keygen -t rsa

এর আউটপুট হবে এমন :
Generating public/private rsa key pair.
Enter file in which to save the key (/home/name/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/name/.ssh/id_rsa.
Your public key has been saved in /home/name/.ssh/id_rsa.pub.
The key fingerprint is:
08:3c:1a:b5:f1:e0:19:13:c5:f4:38:45:ea:e0:1d:91 name@name
The key’s randomart image is:
+–[ RSA 2048]—-+
|    B=+oo        |
|   + OE*         |
|  . O * .        |
|   + * +         |
|  . . + S        |
|                 |
|                 |
|                 |
|                 |
+—————–+

এখানে দুটি কি তৈরি হল। একটি হচ্ছে id_rsa – এটি প্রাইভেট কি (private key), আরেকটি হচ্ছে id_rsa.pub এটি পাবলিক কি (public key)।

২) এখন id_rsa.pub ফাইলটি সার্ভারে কপি করতে হবে (এর জন্য scp কমান্ড ব্যবহার করা যেতে পারে, বা অন্য উপায়েও করা যেতে পারে)।

৩) এবারে ফাইলটি সার্ভারের ~/.ssh/authorized_keys ফাইলে যুক্ত করে দিতে হবে, এই কমান্ড দিয়ে :
cat id_rsa.pub >> /home/name/.ssh/authorized_keys

৪) তারপরে এই কমান্ড দিতে হবে : chmod 600 /home/name/.ssh/authorized_keys (অপশনাল, মানে এই স্টেপ ফলো না করলেও চলে)।

এখন ssh কমান্ড দিয়ে পাসওয়ার্ড ছাড়াই সার্ভারে ঢোকা যাবে! তবে যেই কম্পিউটার থেকে কাজটি করা হয়েছে, মানে যেই কম্পিউটারের পাবলিক কি সার্ভারে কপি করা হয়েছে, সেই কম্পিউটার থেকেই পাসওয়ার্ড ছাড়া সার্ভারে লগিন করা যাবে। অন্য কম্পিউটার থেকে পাসওয়ার্ড লাগবে। আবার চাইলে সার্ভারের নিরাপত্তা বাড়ানোর জন্য পাসওয়ার্ড বেজড লগিন (password based authentication) বন্ধ করে দেওয়া যায়, তাতে যেসব কম্পিউটারের কি সার্ভারের কাছে আছে, কেবল সেসব কম্পিউটার থেকেই সার্ভারে লগিন করা যাবে।

ইঞ্জিনএক্স ইনস্টল করা : উবুন্টু সার্ভার সেটাপ – ২

আগের পর্ব পড়তে এখানে ক্লিক করতে হবে।

ইঞ্জিনএক্স (nginx) হচ্ছে একটি জনপ্রিয় ওয়েব সার্ভার। আগে আমি বেশিরভাগ ক্ষেত্রেই এপাচি (apache) ব্যবহার করতাম, এখন ইঞ্জিনএক্স ব্যবহার করি। তাই এখন ইঞ্জিনএক্স ইনস্টল করে ফেলবো।

প্রথমে সার্ভারে লগিন করতে হবে : ssh -p 1234 user@ip-address

তারপরে নিচের কমান্ড :
sudo apt-get install nginx

ইঞ্জিনএক্স সার্ভারে একটি সার্ভিস হিসেবে চলবে, সেটি চলছে কী না পরীক্ষা করি :
dimik@dimikcomputing:~$ service nginx status
* nginx is running

তার মানে ঠিকঠাক চলছে। তবে আরো চারটি কমান্ড জেনে রাখি :
service nginx start
service nginx stop
service nginx restart
service nginx reload

এখন ব্রাউজারে আইপি-এড্রেস লিখে এন্টার চাপলেই আমরা নিচের ছবিটি দেখবো :

nginx

উবুন্টু সার্ভার সেটাপ – ১

একটি নতুন ভিপিএস (VPS) বা ভার্চুয়াল প্রাইভেট সার্ভার কেনার পরে কী কী জিনিস সেটাপ করতে হয়, কীভাবে করত হয়, সেগুলো নিয়ে আমি কয়েকটি আর্টিকেল লিখব। এই আর্টিকেলে আমরা দেখব ভিপিএস কেনার পরে প্রথমেই কিভাবে সিকিউরিটি একটু বাড়িয়ে নেওয়া যায়।

ubuntu-server-1

আমি ধরে নিচ্ছি যে সার্ভারের অপারেটিং সিস্টেম হচ্ছে উবুন্টু।

প্রথমে সার্ভারে লগিন করতে হবে : ssh root@ip-address

তারপরে প্যাকেজ আপডেট করতে হবে :  apt-get update

অত:পর আপগ্রেডের কাজ : apt-get upgrade

এখন পাইথন ও প্রয়োজনীয় কিছু জিনিস ইনস্টল করে ফেলি। (কী কী প্যাকেজ ইনস্টল হচ্ছে সেটা লেখা আসবে The following NEW packages will be installed: এবং The following extra packages will be installed: এর নিচে।)
root@dimikcomputing:~# apt-get install curl python-software-properties software-properties-common

এখন sudo ইনস্টল করা না থাকে সেটি করে নিতে হবে : apt-get install sudo

সার্ভারের নিরাপত্তার জন্য আমরা নতুন একটি ইউজার তৈরি করবো যার এডমিন প্রিভিলেজ থাকবে। এর জন্য নিচের কমান্ডগুলো একে একে টার্মিনালে দিতে হবে। <USERNAME> এর জায়গায় ইউজারনেম দিতে হবে, মানে যে নামে ইউজার আমরা চাই।

groupadd admin
adduser <USERNAME>
usermod -a -G admin <USERNAME>
dpkg-statoverride –update –add root admin 4750 /bin/su

এখন রুট থেকে আমরা নতুন তৈরি করা ইউজারে চলে যাব :

su <USERNAME>

এখন সার্ভারের SSH পোর্ট পরিবর্তন করে দিব। SSH-এর ডিফল্ট পোর্ট হচ্ছে 22। আমরা 1025 থেকে 65536 এর মধ্যে যেকোনো একটি পোর্ট নির্বাচন করতে পারি। আর রুট থেকে যেন আর লগিন করা না যায়, সেই ব্যবস্থাও করে দিব। এর জন্য একটি ফাইল ওপেন করতে হবে :

sudo vim /etc/ssh/sshd_config

(vim ইনস্টল করা না থাকলে এই কমান্ড দিতে হবে : sudo apt-get install vim)

এখন নিচের দুটি লাইনে পরিবর্তন করতে হবে :

Port 2423
PermitRootLogin no

আমরা পোর্ট নাম্বার পরিবর্তন করে 2423 দিলাম (ডিফল্ট 22 ছিল) এবং PermitRootLogin কে no করে দিলাম (ডিফল্ট yes ছিল)।

তারপরে ফাইলের একেবারে শেষে নিচের লাইন দুটি যোগ করতে হবে  (<USERNAME> এর জায়গায় যেই ইউজারটি একটু আগে তৈরি করা হলো, সেটি লিখতে হবে, এঙ্গেল ব্র্যাকেট ছাড়া):

UseDNS no
AllowUsers <USERNAME>
এবারে ssh রিস্টার্ট করতে হবে :

sudo /etc/init.d/ssh restart

এখন যদি আমাদের ইউজার নেম হয় dimik এবং পোর্ট নাম্বার হয় 2423, তাহলে আমরা এভাবে লগিন করতে পারব :

ssh -p 2423 dimik@ip-address

পরের পর্বগুলোতে আমরা দেখবো কীভাবে বিভিন্ন প্রোগ্রামিং ল্যাঙ্গুয়েজ, ডাটাবেজ, ওয়েবসার্ভার ইত্যাদি ইনস্টল করতে হয়।

নিচের দুটি টিউটোরিয়ালের সাহায্য নিয়েছি :
১) https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-12-04

২) http://learnaholic.me/2014/01/09/ubuntu-vps-step-by-step-config-notes/