লগ, লগ, লগ!

লগ, লগ, লগ!

লার্নিং অনুশীলনী

ভূমিকা

Go-তে rune টাইপটি int32-এর একটি অ্যালিয়াস। এই অন্তর্নিহিত int32 টাইপের কারণে rune টাইপে একটি সাইনড ৩২-বিট ইন্টিজার মান সংরক্ষণ করা হয়। তবে, int32 টাইপের বিপরীতে, rune টাইপে সংরক্ষিত ইন্টিজার মানটি একটি একক ইউনিকোড ক্যারেক্টার বোঝায়।

ইউনিকোড এবং ইউনিকোড কোড পয়েন্ট

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

Go-তে rune টাইপ একটি একক ইউনিকোড কোড পয়েন্ট বোঝায়।

নিচের টেবিলে উদাহরণস্বরূপ কিছু ইউনিকোড ক্যারেক্টার এবং তাদের ইউনিকোড কোড পয়েন্ট ও দশমিক মান দেওয়া হলো:

ইউনিকোড ক্যারেক্টার ইউনিকোড কোড পয়েন্ট দশমিক মান
0 U+0030 48
A U+0041 65
a U+0061 97
¿ U+00BF 191
π U+03C0 960
🧠 U+1F9E0 129504

UTF-8

UTF-8 হলো একটি ভ্যারিয়েবল-প্রস্থের ক্যারেক্টার এনকোডিং, যা প্রতিটি ইউনিকোড কোড পয়েন্টকে ১, ২, ৩ বা ৪ বাইট হিসেবে এনকোড করতে ব্যবহৃত হয়। যেহেতু একটি ইউনিকোড কোড পয়েন্ট সর্বোচ্চ ৪ বাইটে এনকোড করা যায়, তাই rune টাইপকে ৪ বাইট পর্যন্ত ডেটা ধারণ করতে সক্ষম হতে হয়। এ কারণেই rune টাইপ int32-এর একটি অ্যালিয়াস, কারণ একটি int32 টাইপ ৪ বাইট পর্যন্ত ডেটা ধারণ করতে সক্ষম।

Go সোর্স কোড ফাইল UTF-8 ব্যবহার করে এনকোড করা হয়।

রুন ব্যবহার

rune টাইপের ভ্যারিয়েবল ঘোষণা করা হয় একটি ক্যারেক্টারকে একক কোটেশনের ভেতরে রেখে:

myRune := '¿'

যেহেতু rune কেবল int32-এর একটি অ্যালিয়াস, তাই একটি রুনের টাইপ প্রিন্ট করলে int32 পাওয়া যাবে:

myRune := '¿'
fmt.Printf("myRune type: %T\n", myRune)
// Output: myRune type: int32

একইভাবে, একটি রুনের মান প্রিন্ট করলে তার ইন্টিজার (দশমিক) মান পাওয়া যাবে:

myRune := '¿'
fmt.Printf("myRune value: %v\n", myRune)
// Output: myRune value: 191

রুনটি যে ইউনিকোড ক্যারেক্টার বোঝায় তা প্রিন্ট করতে %c ফরম্যাটিং ভার্ব ব্যবহার করুন:

myRune := '¿'
fmt.Printf("myRune Unicode character: %c\n", myRune)
// Output: myRune Unicode character: ¿

রুনটি যে ইউনিকোড কোড পয়েন্ট বোঝায় তা প্রিন্ট করতে %U ফরম্যাটিং ভার্ব ব্যবহার করুন:

myRune := '¿'
fmt.Printf("myRune Unicode code point: %U\n", myRune)
// Output: myRune Unicode code point: U+00BF

রুন এবং স্ট্রিং

Go-তে স্ট্রিং UTF-8 ব্যবহার করে এনকোড করা হয়, যার অর্থ সেগুলোতে ইউনিকোড ক্যারেক্টার থাকে। স্ট্রিংয়ের ক্যারেক্টারগুলো যে ইউনিকোড ক্যারেক্টার বোঝায় তার উপর নির্ভর করে ১, ২, ৩ বা ৪ বাইট হিসেবে সংরক্ষণ ও এনকোড করা হয়।

Go-তে ক্রম বোঝাতে স্লাইস ব্যবহার করা হয় এবং range দিয়ে এই স্লাইসগুলোর উপর ইটারেশন করা যায়। আমরা যখন একটি স্ট্রিংয়ের উপর ইটারেশন করি, Go তখন স্ট্রিংটিকে রুনের একটি সিরিজে রূপান্তর করে, যার প্রতিটি ৪ বাইটের (মনে রাখবেন, রুন টাইপটি int32-এর একটি অ্যালিয়াস!)

যদিও একটি স্ট্রিং কেবল বাইটের একটি স্লাইস, range কিওয়ার্ড একটি স্ট্রিংয়ের বাইটের উপর নয়, বরং তার রুনগুলোর উপর ইটারেশন করে।

এই উদাহরণে, index ভ্যারিয়েবলটি বর্তমান রুনের বাইট সিকোয়েন্সের শুরুর ইনডেক্স বোঝায় এবং char ভ্যারিয়েবলটি বর্তমান রুনটিকে বোঝায়:

myString := "❗hello"
for index, char := range myString {
  fmt.Printf("Index: %d\tCharacter: %c\t\tCode Point: %U\n", index, char, char)
}
// Output:
// Index: 0	Character: ❗		Code Point: U+2757
// Index: 3	Character: h		Code Point: U+0068
// Index: 4	Character: e		Code Point: U+0065
// Index: 5	Character: l		Code Point: U+006C
// Index: 6	Character: l		Code Point: U+006C
// Index: 7	Character: o		Code Point: U+006F

যেহেতু রুনগুলো ১, ২, ৩ বা ৪ বাইট হিসেবে সংরক্ষণ করা যায়, তাই একটি স্ট্রিংয়ের দৈর্ঘ্য সবসময় স্ট্রিংয়ের ক্যারেক্টারের সংখ্যার সমান নাও হতে পারে। একটি স্ট্রিংয়ের দৈর্ঘ্য বাইটে পেতে বিল্ট-ইন len ফাংশন এবং স্ট্রিংয়ে রুনের সংখ্যা পেতে utf8.RuneCountInString ফাংশন ব্যবহার করুন:

import "unicode/utf8"

myString := "❗hello"
stringLength := len(myString)
numberOfRunes := utf8.RuneCountInString(myString)

fmt.Printf("myString - Length: %d - Runes: %d\n", stringLength, numberOfRunes)
// Output: myString - Length: 8 - Runes: 6

নির্দেশনা

আপনার সংস্থার লগ ব্যবস্থাপনায় সহায়তা করার জন্য একটি লগ লাইব্রেরি তৈরির দায়িত্ব আপনাকে দেওয়া হয়েছে। এই লাইব্রেরির সাহায্যে ব্যবহারকারীরা কোন অ্যাপ্লিকেশন একটি নির্দিষ্ট লগ নির্গত করেছে তা শনাক্ত করতে পারবেন, নষ্ট হয়ে যাওয়া লগ ঠিক করতে পারবেন, এবং একটি নির্দিষ্ট লগ লাইন নির্দিষ্ট ক্যারেক্টার সীমার মধ্যে আছে কি না তা নির্ধারণ করতে পারবেন।

1. কোন অ্যাপ্লিকেশন একটি লগ নির্গত করেছে তা শনাক্ত করুন

লগ আসে একাধিক অ্যাপ্লিকেশন থেকে, যার প্রত্যেকে নিজস্ব মালিকানাধীন লগ ফরম্যাট ব্যবহার করে। একটি লগ লগ অ্যাগ্রিগেশন সিস্টেমে সংরক্ষণ করার আগে কোন অ্যাপ্লিকেশনটি লগটি নির্গত করেছে তা শনাক্ত করতে হবে।

এমন একটি Application ফাংশন বাস্তবায়ন করুন যা একটি লগ লাইন নেয় এবং যে অ্যাপ্লিকেশনটি লগ লাইনটি নির্গত করেছে তা রিটার্ন করে।

একটি নির্দিষ্ট লগ লাইন কোন অ্যাপ্লিকেশন নির্গত করেছে তা শনাক্ত করতে, নিচের টেবিলে উল্লেখিত একটি নির্দিষ্ট ক্যারেক্টারের জন্য লগ লাইনটি খুঁজুন:

অ্যাপ্লিকেশন ক্যারেক্টার ইউনিকোড কোড পয়েন্ট
recommendation ❗ U+2757
search 🔍 U+1F50D
weather ☀ U+2600

কোনো লগ লাইনে উপরের টেবিলের কোনো ক্যারেক্টার না থাকলে কলারকে default রিটার্ন করুন। কোনো লগ লাইনে উপরের টেবিলের একটির বেশি ক্যারেক্টার থাকলে, লগ লাইনে বাম থেকে ডানে খুঁজে পাওয়া প্রথম ক্যারেক্টারের সাথে সম্পর্কিত অ্যাপ্লিকেশনটি রিটার্ন করুন।

Application("❗ recommended search product 🔍")
// => recommendation

2. নষ্ট হয়ে যাওয়া লগ ঠিক করুন

লগিং অবকাঠামোতে একটি বিরল কিন্তু দীর্ঘস্থায়ী bug-এর কারণে লগের কিছু ক্যারেক্টার নষ্ট হয়ে যেতে পারে। নষ্ট হওয়া ক্যারেক্টারগুলো এবং তাদের মূল মান শনাক্ত করতে সময় ব্যয় করার পর, আপনি নষ্ট হওয়া লগ ঠিক করতে সহায়তা করার জন্য লগ লাইব্রেরি হালনাগাদ করার সিদ্ধান্ত নেন।

এমন একটি Replace ফাংশন বাস্তবায়ন করুন যা একটি লগ লাইন, একটি নষ্ট হওয়া ক্যারেক্টার এবং মূল মান নেয় এবং একটি পরিবর্তিত লগ লাইন রিটার্ন করে, যেখানে নষ্ট হওয়া ক্যারেক্টারের সব উপস্থিতি মূল মান দিয়ে প্রতিস্থাপিত হয়েছে।

log := "please replace '👎' with '👍'"

Replace(log, '👎', '👍')
// => please replace '👍' with '👍'"

3. একটি লগ প্রদর্শন করা যায় কি না তা নির্ধারণ করুন

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

এমন একটি WithinLimit ফাংশন বাস্তবায়ন করুন যা একটি লগ লাইন এবং ক্যারেক্টার সীমা নেয় এবং লগ লাইনটি ক্যারেক্টার সীমার মধ্যে আছে কি না তা রিটার্ন করে।

WithinLimit("hello❗", 6)
// => true
GitHub-এর মাধ্যমে সম্পাদনা করুন লিংকটি একটি নতুন উইন্ডো বা ট্যাবে খোলে
Go Exercism

লগ, লগ, লগ! শুরু করতে প্রস্তুত?

Exercism-এ সাইন আপ করুন, Go ট্র্যাকের 34টি কনসেপ্ট165টি অনুশীলনী আর সত্যিকারের মানুষের মেন্টরিং দিয়ে শিখুন ও দক্ষ হয়ে উঠুন, সম্পূর্ণ বিনামূল্যে।