কম্পিউটার টিউটোরিয়াল

Ruby-এর বিটওয়াইজ টুলবক্স মাস্টার করুন: অপারেটর, অ্যাপ্লিকেশন এবং চমৎকার ট্রিকস

আপনি সম্ভবত সারাজীবন Rails অ্যাপ বানিয়ে কাটাতে পারেন বিটওয়াইজ অপারেটর ব্যবহার না করেই। আপনি যদি প্রোগ্রামিং-এ নতুন হন, তবে "বিটওয়াইজ" মানে কী সেটাও নাও জানতে পারেন।

কিন্তু য जिस মুহূর্তে আপনি 효율성이 গুরুত্বপূর্ণ এবং রিসোর্স সীমিত এমন সিস্টেমে আগ্রহ নেবেন, বিটওয়াইজ অপারেশন অত্যন্ত গুরুত্বপূর্ণ হয়ে উঠে। নেটওয়ার্ক প্রোটোকল, ক্রিপ্টোগ্রাফি, Unix ফাইল পারমিশন এবং এমবেডেড সিস্টেমে এগুলো ব্যাপকভাবে ব্যবহৃত হয়।

এছাড়া, কম্পিউটার কীভাবে দুটি সংখ্যা যোগ করে সেটি বুঝতে হলে বিটওয়াইজ অপারেশন বুঝতে হবে।

Ruby এবং অনেক ভাষা যেহেতু নেটিভ সাপোর্ট দেয়, তাই এটি আপনার টুলবক্সে যোগ করার জন্য একটি চমৎকার টুল, যদি কেবল ভবিষ্যতে এনকাউন্টার করলে বুঝতে পারেন সেটির জন্যই।

এই আর্টিকেলে আমরা কভার করব বিটওয়াইজ অপারেশন কী, কোথায় অ্যাপ্লাই করা যায় এবং Ruby-এ সেগুলো কীভাবে সেরাভাবে ব্যবহার করা যায়। চলুন শুরু করি।

বিটওয়াইজ অপারেশন কী?

কम्पিউটারের নিম্নতম লেভেলে আমাদের শুধু ১ এবং ০ থাকে, যাকে বিট বলা হয়। Ruby বা অন্য যেকোনো ল্যাঙ্গুয়েজে আমরা যেকোনো অপারেশন ব্যবহার করি, সেগুলো τελেও ১ এবং ০ হিসেবে সংরক্ষিত হয়, কিন্তু আমাদের কম্পিউটারের সফটওয়ার সেগুলো কার্যকরভাবে আমরা যা দেখি এবং যা আসলে স্টোর থাকে তার মধ্যে রূপান্তর করে। উদাহরণস্বরূপ, আমরা "hello" স্ট্রিংটি ১ এবং ০-এর একটি চেইন হিসেবে স্টোর করি।

বিটওয়াইজ অপারেশন আমাদের সরাসরি সেই বিটগুলো (সাধারণত সংখ্যা রিপ্রেজেন্ট করে) অ্যাক্সেস করতে দেয় এবং সেগুলোর সাথে "কিছু" করতে দেয়। কিছু অপারেশন আমাদের সফটওয়ারে ফিচার ইমপ্লিমেন্ট করতে আরও এলিগ্যান্ট এবং ইফিশিয়েন্ট উপায় দেয়।

বিটওয়াইজ অপারেশনের দুটি গুরুত্বপূর্ণ দিক হাইলাইট করছি: এটি তথ্য সংরক্ষণে অত্যন্ত ইফিশিয়েন্ট (কারণ আমরা সরাসরি বিট ব্যবহার করি) এবং এক্সিকিউশনে খুব দ্রুত।

বেসিক বিহেভিয়ার হচ্ছে একটি বিট সেট থাকা এবং সেটিতে অপারেটর অ্যাপ্লাই করা। আপনি দুটি বিট সেটের সাথে ও অপারেটর ব্যবহার করতে পারেন। কিছু অপারেশন দেখি:

NOT বিটওয়াইজ অপারেশন

এটি একটি unary অপারেশন, অর্থাৎ এটি শুধু একটি বিট সেটে প্রয়োগ হয় এবং এটি খুব সহজ: ১ গুলোকে ০ এবং ০ গুলোকে ১ করা। এটি ~ চিহ্নে রিপ্রেজেন্ট করা হয়।

~101000 = 010111 

AND বিটওয়াইজ অপারেশন

AND হলো একটি অপারেশন যা দুটি বিট সেটে প্রয়োগ হয়; এর চিহ্ন & এবং এটি এই লজিক ফলো করে:

1 & 1 = 1
1 & 0 = 0
0 & 1 = 0
0 & 0 = 0 

তবে যখন আমাদের দুটি সমান দৈর্ঘ্যের বিট সেট থাকে, ফলাফল হলো প্রতিটি জোড়ার জন্য এই লজিক অ্যাপ্লাই করা:

0110 AND 0111
-----
0110 

Ruby-এ:

25.to_s(2) # 11001
30.to_s(2) # 11110
(25 & 30).to_s(2) # 11000 

OR বিটওয়াইজ অপারেশন

AND অপারেশনের মতো, দুটি বিট সেটে প্রয়োগ হওয়া আরেকটি অপারেশন হলো বিটওয়াইজ OR। এর চিহ্ন | এবং এটি এই লজিক ফলো করে:

1 | 1 = 1
1 | 0 = 1
0 | 1 = 1
0 | 0 = 0 

তবে যদি যেকোনো পাশে ১ থাকে, ফলাফল ১, অন্যথায় ০। খুব সিম্পল! আরও বিটের সাথে OR অপারেশন দেখি:

0110 OR 0111
-----
0111 

Ruby-এ:

25.to_s(2) # 11001
30.to_s(2) # 11110
(25 | 30).to_s(2) # 11111 

ব্যবহারিক উদাহরণ ১: পারমিশন

এই মুহূর্তে আপনি চিন্তা করতে পারেন এই অপারেশনগুলো কেন উপযোগী। আপনি নেটওয়ার্ক প্রোটোকল, গ্রাফিক্স বা ক্রিপ্টোগ্রাফির সাথে সরাসরি কাজ করার প্ল্যান নাও থাকতে পারেন।

তবে আপনি পারমিশন নিয়ে কাজ করেছেন সম্ভবত। পারমিশন হলো এমন একটি এলাকা যেখানে বিটওয়াইজ অপারেশন খুব কাজে লাগে। কল্পনা করুন আপনার একটি পারমিশন সিস্টেম আছে যেখানে ইউজার ডকুমেন্টে বিভিন্ন অ্যাকশন পারফর্ম করতে পারে:

  • View (দেখা)
  • Edit (সম্পাদনা)
  • Delete (ডিলিট)
  • Invite other users (অন্য ইউজার আমন্ত্রণ)

এখন আমরা এই অ্যাকশনগুলো বিভিন্ন রোলে মডেল করতে চাই:

  • Assistant: ডকুমেন্ট দেখতে এবং এডিট করতে পারবে।
  • Observer: শুধু ডকুমেন্ট দেখতে পারবে।
  • Author: সব অ্যাকশন পারফর্ম করতে পারবে।

এটি কীভাবে মডেল করব? যেকোনো মুহূর্তে কীভাবে জানব একজন ইউজারের এই রোলগুলোর একটি আছে কিনা? একটি উত্তর হলো বিটওয়াইজ অপারেশন ব্যবহার করা।

আমরা প্রতিটি ইউজারের জন্য শুধু একটি বিট সেট সংরক্ষণ করব যা তাদের পারমিশন রিপ্রেজেন্ট করবে:

(ডান পাশ থেকে শুরু)
১ম বিট: View
২য় বিট: Edit
৩য় বিট: Delete
৪র্থ বিট: Invite other users 

উদাহরণস্বরূপ:

0001 = শুধু ডকুমেন্ট দেখতে পারবে।
0011 = ডকুমেন্ট দেখতে এবং এডিট করতে পারবে।
1001 = দেখতে পারবে, এডিট করতে পারবে না, ডিলিট করতে পারবে না এবং অন্যদের আমন্ত্রণ জানাতে পারবে। 

এই মানগুলো কিছু ইউজারের জন্য সেট করলে, আমরা খুব দ্রুত কম্পারিজন করতে পারব যে কোন পারমিশন আছে কিনা। কল্পনা করুন আমরা চেক করছি একজন ইউজার ডকুমেন্ট এডিট করতে পারে কিনা। আমরা বিটওয়াইজ AND অপারেশন ব্যবহার করতে পারি:

# এটি একই বিট মাস্ক। এতে শুধু যে মান চেক করতে চাই সেটি থাকে, এই কেসে এডিটের জন্য দ্বিতীয় বিট।
EDIT_PERMISSION_MASK = 0b0010

# চেক করার জন্য একটি কুইক মেথড:
def can_edit_document?(user_permissions)
  (EDIT_PERMISSION_MASK & user_permissions) != 0
end 

এতে মানে যদি বিটওয়াইজ AND অপারেশন আমাদের ০ ছাড়া কিছু দেয়, তবে আমাদের সেই বিট সেট আছে:

0010 AND 1101
----
0000 == 0 তাই পারমিশন নেই

0010 AND 1110
----
0010 != 0 তাই পারমিশন আছে 

একই লজিক অন্য যেকোনো পারমিশনের জন্য অ্যাপ্লাই করা যায় বিটের পজিশন চেঞ্জ করে, তাই আমরা এই কনস্ট্যান্ট এবং মেথডগুলো পাবো:

VIEW_PERMISSION_MASK = 0b0001
EDIT_PERMISSION_MASK = 0b0010
DELETE_PERMISSION_MASK = 0b0100
INVITE_PERMISSION_MASK = 0b1000 

এছাড়া আমরা ডাইনামিক্যালি পারমিশন ডিফাইন করতে পারি এবং ভবিষ্যতে নতুন পারমিশন সংরক্ষণ করতে পারি একটি কুইক বিট চেক দিয়ে।

উদাহরণস্বরূপ, আমরা আগে বলেছিলাম Assistant শুধু View এবং Edit করতে পারবে, তাই সেই ইউজারের পারমিশন হবে: 0011। আমরা সেটি ডাটাবেসে সংরক্ষণ করতে পারি এবং আগে ডিফাইন করা মেথড দিয়ে সহজে চেক করতে পারি একজন Assistant কোন অ্যাকশন পারফর্ম করতে পারে কিনা।

ASSISTANT_MASK = VIEW_PERMISSION_MASK | EDIT_PERMISSION_MASK # এটি হবে: 0011

# অপশনালি, এই মেথড দিয়ে চেক করা যায় ইউজারটি অ্যাসিস্ট্যান্ট কিনা। এই মেথড User ক্লাসে ডিফাইন করা যেতে পারে।
def is_assistant?(user)
  (user.permissions == ASSISTANT_MASK)
end 

যদি এই সব আপনাকে পরিচিত লাগে, তবে ذेंকারা Unix-বেসড সিস্টেমে ফাইল পারমিশনের জন্য একই অ্যাপ্রোচ ব্যবহার করা হয়।

ব্যবহারিক উদাহরণ ২: টিমে পজিশন

বিটওয়াইজ অপারেশন একটু আর ব্যবহার করি 😉।

আমরা এটিকে আরেকটি সাধারন কেসে অ্যাপ্লাই করতে পারি: স্পোর্টস টিমে বিভিন্ন পজিশন বা কোম্পানিতে জব পজিশন। বাস্কেটবল টিম নিই সিম্পল করতে।

বাস্কেটবলে গেম খেলার সময় ৫টি পজিশন থাকে: - Point guard - Shooting guard - Small forward - Power forward - Center

আমরা প্রতিটি পজিশনের জন্য বিট সেট অ্যাসাইন করতে পারি: 00001 Point guard 00010 Shooting guard 00100 Small forward 01000 Power forward 10000 Center

Ruby-এ একইভাবে:

POINT_GUARD_POSITION = 0b00001
SHOOTING_GUARD_POSITION = 0b00010
SMALL_FORWARD_POSITION = 0b00100
POWER_FORWARD_POSITION = 0b01000
CENTER_POSITION = 0b10000

POINT_GUARD_POSITION | SHOOTING_GUARD_POSITION | SMALL_FORWARD_POSITION | POWER_FORWARD_POSITION | CENTER_POSITION
# = 31 

এখন আমরা কিছু ইন্টারেস্টিং জিনিস করতে পারি, যেমন পুরো টিম উপস্থিত কিনা চেক করা:

# p1...p5 হলো প্রতিটি প্লেয়ারের পজিশন
is_full_team_present = (p1 | p2 | p3 | p4 | p5 == 31) 

কেন? বিটওয়াইজ OR অপারেশন করলে যদি সব পজিশন থাকে, তবে আমরা পাব: 11111।

# OR বিটওয়াইজ অপারেশন
00001 | 00010 | 00100 | 01000 | 10000
-----
11111 

এবং 11111 হচ্ছে 31, কারণ 2^0 + 2^1 + 2^2 + 2^3 + 2^4 = 31।

এটি স্ট্রিক্টলি বিটওয়াইজ অপারেশন-এর লিখিত নয়, কিন্তু এই ডেটা মডেলিং দিয়ে আমরা চেক করতে পারি দুজন প্লেয়ার এক্সচেঞ্জ করা যায় কিনা। এটি খুব সিম্পল:

def can_be_exchanged?(player1, player2)
  player1.position == player2.position
end 

XOR

দুটি বিট সেটের সাথে করা যায় আরেকটি অপারেশন হলো XOR, যার চিহ্ন ^।

XOR মানে Exclusive OR এবং এটি এই লজিক ফলো করে:

1 ^ 1 = 0
1 ^ 0 = 1
0 ^ 1 = 1
0 ^ 0 = 0 

তবে ফলাফল ১ হবে শুধু তখন যখন দুটি বিটের একটিই ১ হবে; যদি দুটোই সমান হয় তবে ০।

এই অপারেশন কিছু অ্যালগরিদমে একটি সংখ্যাকে নিজের সাথে কম্পেয়ার করতে ব্যবহার হয়, কারণ x ^ x = 0।

শিফট (Shifts)

এটি একটি ইন্টারেস্টিং অপারেশন গ্রুপ যেখানে আমরা বিটগুলোকে একটি সেটের ভিতরে এক পাশ থেকে অন্য পাশে "মুভ" বা "শিফট" করি। ব্যাখ্যা করছি।

বিট শিফট দিয়ে আমরা বিটগুলোকে এক ডিরেকশনে, বাম বা ডান দিয়ে সরিয়ে দেই:

00010111 left-shift <-------
00101110 
10010111 right-shift ------->
11001011 

আমরা বিটগুলো n বার মুভ বা শিফট করতে পারি। Ruby-এ ৫ নম্বরকে দুবার লेफট শিফট করার উদাহরণ:

5.to_s(2) # 101
(5 << 2).to_s(2) # 10100 

আপনি দেখছেন, লেফট শিফট রিপ্রেজেন্ট করা হয় << দিয়ে। রাইট শিফট ব্যবহার করে >>:

5.to_s(2) # 101
(5 >> 2).to_s(2) # 1 

এই কেসে আমরা শুধু ১ পাই, কারণ 1*01* থেকে "০" এবং "১" বিটগুলো ডিসকার্ড হয়েছে।

রাইট শিফট দিয়ে ২ দিয়ে ভাগ করা

বিট শিফট সম্পর্কে একটি ইন্টারেস্টিং ফ্যাক্ট হচ্ছে আপনি কিছু ম্যাথমেটিক্যাল অপারেশন এটা দিয়ে কম্পিউট করতে পারেন। অতীতে এটি দ্রুত হতো, কিন্তু আজকাল এটি প্রায় এক্সক্লूसিভলি সেই প্রোগ্রামাররা ব্যবহার করে যারা রিসোর্স কনস্ট্রেইন্টেড এনভায়রনমেন্টে কাজ করে যেমন গেম ডেভেলপমেন্ট।

যদি আমরা একটি সংখ্যার ওপর রাইট শিফট অ্যাপ্লাই করি, তবে আমরা সেটিকে ২ দিয়ে ভাগ করার ফলাফল পাই:

10.to_s(2) # 1010
(10 >> 1).to_s(2) # 101
10 >> 1 # 5 

লেফট শিফট দিয়ে ২ দিয়ে গুণ করা

উसीভাবে, লেফট শিফট দিয়ে ২ দিয়ে গুণ করা যায়:

10.to_s(2) # 1010
(10 << 1).to_s(2) # 10100
10 << 1 # 20 

খুব দ্রুত চেক করুন কোন সংখ্যা অড্ড নাকি ইভেন

বিটওয়াইজ অপারেশনের একটি খুব সিম্পল উদাহরণ আছে যা খুব দ্রুত এবং ফলো করা সহজ।

কল্পনা করুন আমরা ১ দিয়ে AND অপারেশন করি, শুধু ১। সেটি হবে যেকোনো সংখ্যক ০ (কম্পিউটারের উপর নির্ভর করে) এবং ১। ২ দিয়ে করি:

2 = 00000010
& 00000001
-------------
00000000 

এবার ৪ দিয়ে:

4 = 00000100
& 00000001
-------------
00000000 

৫ দিয়ে কী হয়?

5 = 00000101
& 00000001
-------------
00000001 

এবার আমরা ১ পেলাম। অনুমান করতে পারেন কী মানে?

১ দিয়ে এই AND করলে, যদি সংখ্যা ইভেন হয়, আমরা ০ পাব। যদি অড্ড হয়, ১ পাব। এই ফ্যাক্ট ব্যবহার করে Ruby-এ কুইক মেথড বানাতে পারি:

def is_odd?(number)
  number & 1
end 
def is_even?(number)
  is_odd?(number) == 0
end

# অথবা:
def is_even?(number)
  (number & 1) == 0
end 

আরও বিটওয়াইজ ট্রিকস জানতে এই কালেকশনটি দেখুন।

উপসংহার

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

  1. পাইথন বিটওয়াইজ অপারেটর (Python Bitwise Operators)

  2. ওয়ানডোজ ১০ টিপস এবং ট্রিকস

  3. উইন্ডোজ ১০ টিপস এবং ট্রিকস: ৫০+ কাজের টিপস

  4. Apple Magic Mouse মास্টার করুন: প্রো টিপস অ্যান্ড ট্রিকস অপ্টিমাল পারফরম্যান্সের জন্য