আপনি যদি এমন একটি লাইব্রেরির জন্য ইন্টারনেটে অনুসন্ধান করেন যা সিকোয়েন্স তৈরি করতে পারে, আপনি খুব কমই একটি খুঁজে পাবেন, যদিও সিকোয়েন্সগুলি পৃথক গণিত এবং কম্পিউটার বিজ্ঞানের মূল ধারণা।
এই সংক্ষিপ্ত নিবন্ধে, আমরা SeqGen নামক সিকোয়েন্স জেনারেশনের জন্য আমি লিখেছিলাম এমন একটি লাইব্রেরির দিকে নজর দেব।
একটি ক্রম (অনানুষ্ঠানিকভাবে বলা) হল উপাদানগুলির একটি সেট (বেশিরভাগ সংখ্যা) যেখানে প্রতিটি উপাদানের উত্পাদন পূর্ববর্তী উপাদান(গুলি) এর উপর ভিত্তি করে।
সবচেয়ে মৌলিক উদাহরণ হল ধনাত্মক পূর্ণসংখ্যার একটি সরল রৈখিক ক্রম যেখানে প্রথম উপাদানটি 0 এবং পরবর্তী উপাদানটি পূর্ববর্তী উপাদান প্লাস ওয়ান, তাই আমরা প্রথমটির সাথে একটি যোগ করে দ্বিতীয় উপাদানটি পেতে পারি এবং আমরা তৃতীয়টি পেতে পারি উপাদান এক যোগ করে দ্বিতীয় এক, এবং তাই. রৈখিক ক্রমটি দেখতে এরকম হবে: {0, 1, 2, 3, …, n}
।
একটি আরও জটিল উদাহরণ হতে পারে ফিবোনাচি ক্রম যেখানে প্রথম দুটি উপাদান হল 0 এবং 1, এবং পরবর্তী উপাদানটি হল দুটি পূর্ববর্তী উপাদানের যোগফল। ফিবোনাচি ক্রমটি দেখতে এইরকম হবে: {0, 1, 1, 2, 3, 5, 8, 13, 21, …, n}
আমরা উপরে থেকে লক্ষ্য করতে পারি যে একটি ক্রম দুটি বৈশিষ্ট্য দ্বারা সংজ্ঞায়িত করা হয়েছে:
2.0_
নির্ভরতা:SeqGen লাইব্রেরি রাস্ট প্রোগ্রামিং ভাষায় লেখা হয়; ফলো আপ করার জন্য, আপনাকে মরিচা ইনস্টল করতে হবে।
2.1_
একটি প্রকল্প তৈরি করা:আসুন SeqGen লাইব্রেরি ব্যবহার করার জন্য একটি নতুন প্রকল্প তৈরি করি; আমরা পণ্যসম্ভার দিয়ে তা করতে পারি:
$ cargo new --bin sequence && cd sequence
এখন, আমাদের প্রকল্পে নির্ভরতা হিসাবে লাইব্রেরি যোগ করা যাক:
$ cargo add seqgen
এখন, আমরা লাইব্রেরি ব্যবহার করার জন্য প্রস্তুত।
SeqGen-এ, সিকোয়েন্স তৈরির প্রক্রিয়াটি সিকোয়েন্সের দুটি বৈশিষ্ট্যের সাথে সরাসরি ম্যাপ করে যা আমরা একটি সিকোয়েন্স বিভাগে কী বলেছি; আমাদের প্রাথমিক উপাদান এবং পরবর্তী উপাদান (SeqGen-এ ট্রানজিশন ফাংশন বলা হয়) তৈরি করে এমন ফাংশন সংজ্ঞায়িত করতে হবে।
রৈখিক ক্রম তৈরি করা যাক:
use seqgen::prelude::*; fn main() { let linear_seq = Sequence::new() .initial_elements(vec![0]) .transition_function(|alive_elements, current_element_index| { alive_elements.last_element().unwrap() + 1 }); }
Sequence
টাইপ হল একটি স্ট্রাকট যা একটি সিকোয়েন্সকে প্রতিনিধিত্ব করে; এই ধরণের সম্পর্কিত ফাংশনটিকে new()
কল করে, আমরা একটি নতুন উদাহরণ পাই যা অনির্ধারিত। এই অনির্ধারিত উদাহরণে, আমরা এটিকে সংজ্ঞায়িত করার জন্য পদ্ধতিগুলিকে কল করতে পারি।
প্রথম পদ্ধতিটি হল initial_elements()
যেটি উপাদানগুলির একটি ভেক্টরকে একটি যুক্তি হিসাবে গ্রহণ করে এবং এটিকে উদাহরণের প্রাথমিক উপাদান হিসাবে সেট করে।
দ্বিতীয় পদ্ধতিটি হল transition_function()
যা একটি যুক্তি হিসাবে একটি ক্লোজার নেয় যা বর্তমানে উপলব্ধ উপাদান থেকে পরবর্তী উপাদানে রূপান্তরকে প্রতিনিধিত্ব করে।
এই বন্ধের দুটি আর্গুমেন্টের অ্যাক্সেস রয়েছে: প্রথমটি হল alive_elements
যা বর্তমানে উপলব্ধ উপাদানগুলির প্রতিনিধিত্ব করে এবং দ্বিতীয়টি হল current_element_index
(টাইপ usize
) যা প্রজন্মের বর্তমান উপাদানটির সূচক। ট্রানজিশন ফাংশনের একটি চিত্রের জন্য নীচের টেবিলটি দেখুন।
প্রজন্মের বর্তমান উপাদান | জীবন্ত_উপাদান | বর্তমান_উপাদান_সূচক |
---|---|---|
| | |
| | |
| | |
| | |
alive_elements
হল SequencePart
SequencePart
যেহেতু উপাদানটির সূচীটিও রৈখিক অনুক্রমে এর মান, তাই আমরা উপরের উদাহরণটিকে সহজ করতে পারি:
use seqgen::prelude::*; fn main() { let linear_seq = Sequence::new().transition_function(|_, i| i); }
এখানে, আমাদের প্রাথমিক উপাদানগুলি সংজ্ঞায়িত করার প্রয়োজন নেই, এবং আমাদের লাইভ উপাদানগুলিতে অ্যাক্সেসের প্রয়োজন নেই; আমাদের শুধু সূচী প্রয়োজন (যার নাম এই ক্ষেত্রে i
), এবং আমরা কেবল এটি ফেরত দিই।
একই পদ্ধতিতে, আমরা ফিবোনাচি ক্রম সংজ্ঞায়িত করতে পারি:
use seqgen::prelude::*; fn main() { let fib_seq = Sequence::new() .initial_elements(vec![0, 1_u128]) .transition_function(|alive_elements, i| { let x = alive_elements.nth_element(i - 1).unwrap(); let y = alive_elements.nth_element(i - 2).unwrap(); x + y }); }
যেহেতু ফিবোনাচি সিকোয়েন্স দ্রুতগতিতে বৃদ্ধি পায়, তাই এই সংজ্ঞার সাথে 187টির বেশি উপাদান তৈরি করলে u128
ওভারফ্লো হবে। একটি ভাল সংজ্ঞা u128
এর পরিবর্তে বড় int ব্যবহার করবে।
আমরা আমাদের ক্রম সংজ্ঞায়িত করার পরে, আমরা এর উপাদানগুলি অ্যাক্সেস করতে পারি:
use seqgen::prelude::*; fn main() { let mut linear_seq = Sequence::new().transition_function(|_, i| i); let some_element = linear_seq.nth_element(111); println!("{some_element}"); }
এখানে, আমরা nth_element()
পদ্ধতি ব্যবহার করে 111 তম উপাদান অ্যাক্সেস করছি যা উপাদানটির একটি অপরিবর্তনীয় রেফারেন্স প্রদান করে ( &usize
)।
লক্ষ্য করুন যে আমরা linear_seq
পরিবর্তনযোগ্য করেছি। কারণ nth_element()
পদ্ধতিটি সিকোয়েন্সের জীবন্ত উপাদানগুলিকে পরিবর্তন করবে।
এইভাবে, আমরা সিকোয়েন্সের যেকোন এলিমেন্ট অ্যাক্সেস করতে পারি ( 0
এর সূচক সহ উপাদান থেকে usize::MAX
এর একটি সূচক সহ উপাদান পর্যন্ত।)
আমরা যেকোন রাস্ট ইটারেটরের মতো ক্রমটি পুনরাবৃত্তি করতে পারি:
use seqgen::prelude::*; fn main() { let linear_seq = Sequence::new().transition_function(|_, i| i); linear_seq.for_each(|e| println!("{e}")); }
এই কোডটি অনুক্রমের সমস্ত উপাদান মুদ্রণ করবে (উপাদান 0
থেকে উপাদান usize::MAX
পর্যন্ত):
$ cargo run -q 0 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
আমরা নিম্নলিখিত কোড ব্যবহার করে ক্রম থেকে বিজোড় উপাদান পেতে পারি:
use seqgen::prelude::*; fn main() { let linear_seq = Sequence::new().transition_function(|_, i| i); let odd_elements = linear_seq.filter(|e| e % 2 != 0); odd_elements.for_each(|e| println!("{e}")); }
আউটপুট:
$ cargo run -q 1 3 5 7 9 11 13 ...
আমরা যে ক্রমটি সংজ্ঞায়িত করি তা অলস, মানে উপাদানগুলি তৈরি করা হবে না যদি না প্রয়োজন হয় (পুনরাবৃত্তির ক্ষেত্রে), বা স্পষ্টভাবে অনুরোধ করা হয় ( nth_element()
পদ্ধতি ব্যবহার করে)।
কখনও কখনও, আমাদের শুধুমাত্র একটি অনুক্রমের অংশগুলির সাথে কাজ করতে হবে, এই ক্ষেত্রে, আমাদের ক্রম অংশ রয়েছে।
ক্রম অংশ তিন ধরনের আছে:
AliveElementsPart
ImmutableRangePart
MutableRangePart
জীবন্ত উপাদান অংশ:
আমরা সিকোয়েন্সে alive_elements()
পদ্ধতি ব্যবহার করে লাইভ উপাদান পেতে পারি:
use seqgen::prelude::*; fn main() { let linear_seq = Sequence::new() .transition_function(|_, i| i) .pre_generate(111); let alive_elements = linear_seq.alive_elements(); for alive_element in alive_elements { print!("{alive_element} "); } }
এই কোডটি সমস্ত জীবন্ত উপাদান প্রিন্ট করবে (এই ক্ষেত্রে 0 থেকে 110 কারণ আমরা 111টি উপাদান পূর্বে তৈরি করেছি)।
অপরিবর্তনীয় রেঞ্জ পার্ট:
অপরিবর্তনীয় ব্যাপ্তি হল জীবন্ত উপাদানের ব্যাপ্তি; তারা ক্রম পরিবর্তন করতে পারে না. আপনি যদি একটি অপরিবর্তনীয় পরিসর তৈরি করেন এবং এর সমস্ত উপাদান জীবিত না থাকে তবে আপনি একটি ত্রুটি পাবেন ( DeadRange
ত্রুটি)।
আমরা range()
পদ্ধতি ব্যবহার করে একটি অপরিবর্তনীয় পরিসর তৈরি করতে পারি যা একটি Result
প্রদান করে। Ok
ভেরিয়েন্ট হল ImmutableRangePart
, এবং Err
ভেরিয়েন্ট হল RangeError
। RangeError
হতে পারে InvalidRange
ভেরিয়েন্ট (যদি পরিসরের শুরু তার শেষের চেয়ে বড় হয়), অথবা এটি DeadRange
ভেরিয়েন্ট হতে পারে (যদি পরিসরের সমস্ত উপাদান জীবিত না থাকে):
use seqgen::prelude::*; fn main() { let linear_seq = Sequence::new().transition_function(|_, i| i); let range = linear_seq.range(0, 3).unwrap(); for e in range { println!("{e}") } }
এই কোডটি DeadRange
ত্রুটির সাথে আতঙ্কিত হবে কারণ কোন জীবন্ত উপাদান নেই। আমরা নিম্নলিখিতগুলির সাথে এটি সংশোধন করতে পারি:
use seqgen::prelude::*; fn main() { let mut linear_seq = Sequence::new().transition_function(|_, i| i); linear_seq.generate(3); let range = linear_seq.range(0, 3).unwrap(); for e in range { println!("{e}") } }
এখানে, আমরা পরিসীমা বৈধ করতে 3টি উপাদান তৈরি করেছি।
পরিবর্তনযোগ্য রেঞ্জ পার্ট:
একটি পরিবর্তনযোগ্য পরিসর অনুক্রমকে পরিবর্তন করতে পারে (উপাদান তৈরি করে)।
আমরা এর মত একটি পরিবর্তনযোগ্য পরিসীমা ব্যবহার করতে পারি:
use seqgen::prelude::*; fn main() { let mut linear_seq = Sequence::new().transition_function(|_, i| i); let mut_range = linear_seq.range_mut(0, 111).unwrap(); for e in mut_range { println!("{e}"); } }
এই কোডটি 0 থেকে 110 পর্যন্ত উপাদান প্রিন্ট করবে।
শেষ পর্যন্ত এই নিবন্ধটি পড়ার জন্য আপনাকে ধন্যবাদ, এবং আমি আশা করি আপনি এটিতে কিছু দরকারী খুঁজে পেয়েছেন। যদি আপনার কাছে এই লাইব্রেরির উন্নতি করতে পারে এমন কোনো পরামর্শ থাকে, তাহলে অনুগ্রহ করে GitHub-এ একটি সমস্যা খুলুন , এবং আপনি যদি লাইব্রেরিতে অবদান রাখতে চান, তাহলে সেটা চমৎকার হবে।
এছাড়াও এখানে প্রকাশিত